3063 changed files with 450621 additions and 3 deletions
-
3chatto/src/main/javascript/app.css
-
557chatto/src/main/javascript/chat.js
-
1chatto/src/main/javascript/node_modules/.bin/atob
-
1chatto/src/main/javascript/node_modules/.bin/handlebars
-
1chatto/src/main/javascript/node_modules/.bin/markdown-it
-
1chatto/src/main/javascript/node_modules/.bin/mime
-
1chatto/src/main/javascript/node_modules/.bin/uglifyjs
-
1chatto/src/main/javascript/node_modules/.bin/which
-
51chatto/src/main/javascript/node_modules/.yarn-integrity
-
38chatto/src/main/javascript/node_modules/alertifyjs/.jshintrc
-
22chatto/src/main/javascript/node_modules/alertifyjs/CONTRIBUTING.md
-
235chatto/src/main/javascript/node_modules/alertifyjs/Gruntfile.js
-
674chatto/src/main/javascript/node_modules/alertifyjs/LICENSE
-
85chatto/src/main/javascript/node_modules/alertifyjs/README.md
-
165chatto/src/main/javascript/node_modules/alertifyjs/RELEASENOTES.md
-
56chatto/src/main/javascript/node_modules/alertifyjs/package.json
-
93chatto/src/main/javascript/node_modules/alertifyjs/src/js/alert.js
-
264chatto/src/main/javascript/node_modules/alertifyjs/src/js/alertify.js
-
186chatto/src/main/javascript/node_modules/alertifyjs/src/js/confirm.js
-
109chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/actions.js
-
274chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/commands.js
-
405chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/dialog.js
-
201chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/events.js
-
122chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/focus.js
-
609chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/intro.js
-
215chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/move.js
-
1chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/outro.js
-
220chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/resize.js
-
65chatto/src/main/javascript/node_modules/alertifyjs/src/js/dialog/transition.js
-
131chatto/src/main/javascript/node_modules/alertifyjs/src/js/event.js
-
217chatto/src/main/javascript/node_modules/alertifyjs/src/js/intro.js
-
322chatto/src/main/javascript/node_modules/alertifyjs/src/js/notifier.js
-
14chatto/src/main/javascript/node_modules/alertifyjs/src/js/outro.js
-
176chatto/src/main/javascript/node_modules/alertifyjs/src/js/prompt.js
-
921chatto/src/main/javascript/node_modules/alertifyjs/src/less/alertify.less
-
73chatto/src/main/javascript/node_modules/alertifyjs/src/less/themes/bootstrap.less
-
91chatto/src/main/javascript/node_modules/alertifyjs/src/less/themes/default.less
-
102chatto/src/main/javascript/node_modules/alertifyjs/src/less/themes/semantic.less
-
185chatto/src/main/javascript/node_modules/argparse/CHANGELOG.md
-
21chatto/src/main/javascript/node_modules/argparse/LICENSE
-
257chatto/src/main/javascript/node_modules/argparse/README.md
-
3chatto/src/main/javascript/node_modules/argparse/index.js
-
146chatto/src/main/javascript/node_modules/argparse/lib/action.js
-
53chatto/src/main/javascript/node_modules/argparse/lib/action/append.js
-
47chatto/src/main/javascript/node_modules/argparse/lib/action/append/constant.js
-
40chatto/src/main/javascript/node_modules/argparse/lib/action/count.js
-
47chatto/src/main/javascript/node_modules/argparse/lib/action/help.js
-
50chatto/src/main/javascript/node_modules/argparse/lib/action/store.js
-
43chatto/src/main/javascript/node_modules/argparse/lib/action/store/constant.js
-
27chatto/src/main/javascript/node_modules/argparse/lib/action/store/false.js
-
26chatto/src/main/javascript/node_modules/argparse/lib/action/store/true.js
-
149chatto/src/main/javascript/node_modules/argparse/lib/action/subparsers.js
-
47chatto/src/main/javascript/node_modules/argparse/lib/action/version.js
-
482chatto/src/main/javascript/node_modules/argparse/lib/action_container.js
-
14chatto/src/main/javascript/node_modules/argparse/lib/argparse.js
-
50chatto/src/main/javascript/node_modules/argparse/lib/argument/error.js
-
54chatto/src/main/javascript/node_modules/argparse/lib/argument/exclusive.js
-
75chatto/src/main/javascript/node_modules/argparse/lib/argument/group.js
-
1161chatto/src/main/javascript/node_modules/argparse/lib/argument_parser.js
-
21chatto/src/main/javascript/node_modules/argparse/lib/const.js
-
87chatto/src/main/javascript/node_modules/argparse/lib/help/added_formatters.js
-
795chatto/src/main/javascript/node_modules/argparse/lib/help/formatter.js
-
76chatto/src/main/javascript/node_modules/argparse/lib/namespace.js
-
57chatto/src/main/javascript/node_modules/argparse/lib/utils.js
-
70chatto/src/main/javascript/node_modules/argparse/package.json
-
21chatto/src/main/javascript/node_modules/arr-diff/LICENSE
-
130chatto/src/main/javascript/node_modules/arr-diff/README.md
-
47chatto/src/main/javascript/node_modules/arr-diff/index.js
-
109chatto/src/main/javascript/node_modules/arr-diff/package.json
-
21chatto/src/main/javascript/node_modules/arr-flatten/LICENSE
-
86chatto/src/main/javascript/node_modules/arr-flatten/README.md
-
22chatto/src/main/javascript/node_modules/arr-flatten/index.js
-
113chatto/src/main/javascript/node_modules/arr-flatten/package.json
-
21chatto/src/main/javascript/node_modules/arr-union/LICENSE
-
99chatto/src/main/javascript/node_modules/arr-union/README.md
-
29chatto/src/main/javascript/node_modules/arr-union/index.js
-
108chatto/src/main/javascript/node_modules/arr-union/package.json
-
21chatto/src/main/javascript/node_modules/array-unique/LICENSE
-
77chatto/src/main/javascript/node_modules/array-unique/README.md
-
43chatto/src/main/javascript/node_modules/array-unique/index.js
-
96chatto/src/main/javascript/node_modules/array-unique/package.json
-
21chatto/src/main/javascript/node_modules/assign-symbols/LICENSE
-
73chatto/src/main/javascript/node_modules/assign-symbols/README.md
-
40chatto/src/main/javascript/node_modules/assign-symbols/index.js
-
71chatto/src/main/javascript/node_modules/assign-symbols/package.json
-
230chatto/src/main/javascript/node_modules/atob/LICENSE
-
319chatto/src/main/javascript/node_modules/atob/LICENSE.DOCS
-
49chatto/src/main/javascript/node_modules/atob/README.md
-
6chatto/src/main/javascript/node_modules/atob/bin/atob.js
-
24chatto/src/main/javascript/node_modules/atob/bower.json
-
44chatto/src/main/javascript/node_modules/atob/browser-atob.js
-
7chatto/src/main/javascript/node_modules/atob/node-atob.js
-
53chatto/src/main/javascript/node_modules/atob/package.json
-
18chatto/src/main/javascript/node_modules/atob/test.js
-
21chatto/src/main/javascript/node_modules/base/LICENSE
-
491chatto/src/main/javascript/node_modules/base/README.md
-
435chatto/src/main/javascript/node_modules/base/index.js
-
21chatto/src/main/javascript/node_modules/base/node_modules/define-property/LICENSE
-
95chatto/src/main/javascript/node_modules/base/node_modules/define-property/README.md
-
31chatto/src/main/javascript/node_modules/base/node_modules/define-property/index.js
@ -0,0 +1,3 @@ |
|||
@import url("node_modules/alertifyjs/build/css/alertify.css"); |
|||
@import url("node_modules/alertifyjs/build/css/themes/bootstrap.min.css"); |
|||
@import url("node_modules/alertifyjs/build/css/themes/default.min.css"); |
@ -0,0 +1,557 @@ |
|||
// import { sprintf } from 'sprintf-js';
|
|||
// import { vsprintf } from 'sprintf-js';
|
|||
/*var off_payment_method = document.getElementsByName('offline_payment_method'); |
|||
var ischecked_method = false; |
|||
for ( var i = 0; i < off_payment_method.length; i++) { |
|||
if(off_payment_method[i].checked) { |
|||
ischecked_method = true; |
|||
break; |
|||
} |
|||
} |
|||
if(!ischecked_method) { //payment method button is not checked
|
|||
alert("Please choose Offline Payment Method"); |
|||
}*/ |
|||
var css = require('./app.css'); |
|||
console.log(css); |
|||
var log = require('loglevel'); |
|||
var alertify = require('alertifyjs'); |
|||
require('sjcl'); |
|||
var md = require('markdown-it')(); |
|||
var Handlebars = require('handlebars'); |
|||
var DOMPurify = require('dompurify'); |
|||
require('fuse.js'); |
|||
|
|||
var toUserRadios = document.getElementsByName('toUser'); |
|||
var isCheckedUser = false; |
|||
var chatTextArea = document.getElementById('chatTextArea'); |
|||
|
|||
var postNewMessageUrl = `http://${hostAddress}/api/chat/post/message`; //hostAddress variable is set in the thymeleaf head fragment
|
|||
var getAllMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`; |
|||
var getNewMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`; |
|||
var getActiveUsersUrl = `http://${hostAddress}/api/chat/get/active-users/`; |
|||
// var postNewMessageUrl = "http://localhost:8080/api/chat/post/message";
|
|||
// var getAllMessagesUrl = "http://localhost:8080/api/chat/get/messages/";
|
|||
// var getNewMessagesUrl = "http://localhost:8080/api/chat/get/messages/";
|
|||
// var messageLog = [];
|
|||
var username = localStorage.getItem('username'); |
|||
var authToken = localStorage.getItem('authToken'); |
|||
|
|||
var passphraseInput = document.getElementById('passphrase'); |
|||
var iterations = 100000; |
|||
|
|||
var source = document.getElementById("msg_container_template").innerHTML; |
|||
var msgContainerTemplate = Handlebars.compile(source); |
|||
var source = document.getElementById("msg_container_send_template").innerHTML; |
|||
var msgContainerSendTemplate = Handlebars.compile(source); |
|||
var source = document.getElementById("user-contact-online-template").innerHTML; |
|||
var userContactOnlineTemplate = Handlebars.compile(source); |
|||
var source = document.getElementById("user-contact-offline-template").innerHTML; |
|||
var userContactOfflineTemplate = Handlebars.compile(source); |
|||
|
|||
var chatAreaNew = document.getElementById('chat_area_new'); |
|||
|
|||
var userBoxes = document.getElementsByName('user-box'); |
|||
|
|||
|
|||
|
|||
var activeUsers = {}; |
|||
|
|||
var fuseOptions = { |
|||
shouldSort: true, |
|||
threshold: 0.01, |
|||
location: 0, |
|||
distance: 100, |
|||
maxPatternLength: 32, |
|||
minMatchCharLength: 1, |
|||
keys: [ |
|||
"userName", |
|||
] |
|||
}; |
|||
|
|||
log.setLevel('TRACE'); |
|||
|
|||
alertify.set('notifier', 'position', 'top-center'); |
|||
|
|||
// Loop through the buttons and add the active class to the current/clicked button
|
|||
// for (var i = 0; i < btns.length; i++) {
|
|||
// btns[i].addEventListener("click", function() {
|
|||
// var current = document.getElementsByClassName("active");
|
|||
|
|||
// // If there's no active class
|
|||
// if (current.length > 0) {
|
|||
// current[0].className = current[0].className.replace(" active", "");
|
|||
// }
|
|||
|
|||
// // Add the active class to the current/clicked button
|
|||
// this.className += " active";
|
|||
// });
|
|||
// }
|
|||
|
|||
getActiveUsers(authToken) |
|||
.then(data => { |
|||
// activeUsers = data;
|
|||
sessionStorage.setItem('activeUsers', JSON.stringify(data)); |
|||
log.log(sessionStorage.getItem('activeUsers')); |
|||
}) |
|||
|
|||
for (let i = 0; i < userBoxes.length; i++) { |
|||
userBoxes[i].addEventListener('click', userCallBack) |
|||
} |
|||
|
|||
function addUserCallBacks() { |
|||
for (let i = 0; i < userBoxes.length; i++) { |
|||
userBoxes[i].addEventListener('click', userCallBack) |
|||
} |
|||
} |
|||
|
|||
function userCallBack() { |
|||
let current = document.getElementsByClassName('user-box active'); |
|||
let passphrase = passphraseInput.value; |
|||
if (current.length > 0) { |
|||
if (passphrase == '') { |
|||
// alert('Please input passphrase')
|
|||
alertify.error('Please enter a passphrase'); |
|||
return; |
|||
} |
|||
current[0].className = current[0].className.replace(" active", ""); |
|||
|
|||
} |
|||
// Add the active class to the current/clicked button
|
|||
else if (current.length == 0) { |
|||
let elem = document.getElementById('passphrase-initial'); |
|||
passphrase = elem.value; |
|||
if (passphrase == '') { |
|||
// alert('Please input passphrase')
|
|||
alertify.error('Please enter a passphrase'); |
|||
return; |
|||
} |
|||
document.getElementById('no-user-selected').hidden = true; |
|||
document.getElementById('chat-card').hidden = false; |
|||
elem.hidden = true; |
|||
} |
|||
// console.log(this.getElementsByClassName('to-user-span'));
|
|||
let userName = this.getElementsByClassName('to-user-span')[0].innerText; |
|||
document.getElementById('user-name-span').innerText = userName; |
|||
populateMessages(userName, passphrase); |
|||
sessionStorage.setItem('selectedUser', userName); |
|||
this.className += " active"; |
|||
} |
|||
|
|||
function populateMessages(userName, passphrase) { |
|||
console.log('Selected user = ' + userName); |
|||
if (passphrase == '') { |
|||
alert('Please input passphrase') |
|||
return; |
|||
} |
|||
// console.log(userName);
|
|||
if (sessionStorage.getItem(userName) == null) { |
|||
chatTextArea.textContent = ''; |
|||
chatAreaNew.innerHTML = ''; |
|||
getAllMessages(userName) |
|||
.then(json => { |
|||
if (json == null) return; |
|||
console.log(json); |
|||
let i = 0; |
|||
let messageLog = []; |
|||
let messageLogNew = []; |
|||
let lastMessageTimeStamp; |
|||
|
|||
if (json.length > 0) { |
|||
json.forEach(function(obj) { |
|||
// console.log(obj.toUser);
|
|||
messageCipher = JSON.stringify(obj.messageCipher); |
|||
console.log(messageCipher); |
|||
// let message = sjcl.decrypt("password", messageCipher);
|
|||
let message = md.render(sjcl.decrypt(passphrase, messageCipher)); |
|||
let utcDate = obj.messageTime; |
|||
lastMessageTimeStamp = utcDate; |
|||
let localDate = new Date(utcDate); |
|||
let messageLine = sprintf('%s %s: %s ', localDate, obj.fromUser, message); |
|||
|
|||
|
|||
// localDate.``
|
|||
// console.log('localDate = ' + localDate);
|
|||
console.log(messageLine); |
|||
// chatTextArea.append(obj.fromUser + ": " + message + "\n");
|
|||
chatTextArea.append(messageLine + '\n'); |
|||
messageLog[i++] = messageLine; |
|||
chatTextArea.scrollTop = chatTextArea.scrollHeight; |
|||
// console.log('Message log = ' + messageLog);
|
|||
|
|||
let context = { fromUser: obj.fromUser, message: message, time: localDate.toLocaleString() }; |
|||
let msgContainer; |
|||
if (obj.fromUser == username) { |
|||
msgContainer = msgContainerSendTemplate(context); |
|||
} else { |
|||
msgContainer = msgContainerTemplate(context); |
|||
} |
|||
|
|||
messageLogNew.push(JSON.stringify(context)); |
|||
$(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); |
|||
|
|||
|
|||
}); |
|||
sessionStorage.setItem(userName, JSON.stringify(messageLog)); |
|||
sessionStorage.setItem(userName + username + 'new', JSON.stringify(messageLogNew)); |
|||
// console.log()
|
|||
// sessionStorage.clear();
|
|||
console.log('Last message time = ' + lastMessageTimeStamp); |
|||
sessionStorage.setItem(userName + '-time', lastMessageTimeStamp); |
|||
|
|||
|
|||
} |
|||
}); |
|||
} else { |
|||
|
|||
|
|||
console.log("Stored messages = " + sessionStorage.getItem(userName)); |
|||
let storedMessages = JSON.parse(sessionStorage.getItem(userName)); |
|||
let storedMessagesNew = JSON.parse(sessionStorage.getItem(userName + username + 'new')); |
|||
let lastMessageTime = sessionStorage.getItem(userName + '-time'); |
|||
console.log("last message time stamp = " + lastMessageTime); |
|||
if (lastMessageTime != null) { |
|||
getNewMessages(userName, lastMessageTime) |
|||
.then(json => { |
|||
if (json == null) return; |
|||
console.log(json) |
|||
if (json.length > 0) { |
|||
json.forEach(function(obj) { |
|||
let messageCipher = JSON.stringify(obj.messageCipher); |
|||
let message = md.render(sjcl.decrypt(passphrase, messageCipher)); |
|||
// console.log(message);
|
|||
// chatTextArea.append(message + "\n");
|
|||
let utcDate = obj.messageTime; |
|||
lastMessageTimeStamp = utcDate; |
|||
let localDate = new Date(utcDate); |
|||
let messageLine = sprintf('%s %s: %s', localDate, obj.fromUser, message); |
|||
|
|||
// localDate.``
|
|||
// console.log('localDate = ' + localDate);
|
|||
console.log(messageLine); |
|||
// chatTextArea.append(obj.fromUser + ": " + message + "\n");
|
|||
chatTextArea.append(messageLine + '\n'); |
|||
chatTextArea.scrollTop = chatTextArea.scrollHeight; |
|||
storedMessages.push(messageLine); |
|||
|
|||
let context = { fromUser: obj.fromUser, message: message, time: localDate.toLocaleString() }; |
|||
let msgContainer; |
|||
if (obj.fromUser == username) { |
|||
msgContainer = msgContainerSendTemplate(context); |
|||
} else { |
|||
msgContainer = msgContainerTemplate(context); |
|||
} |
|||
|
|||
storedMessagesNew.push(JSON.stringify(context)); |
|||
$(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); |
|||
|
|||
}) |
|||
sessionStorage.setItem(userName + '-time', lastMessageTimeStamp); |
|||
sessionStorage.setItem(userName, JSON.stringify(storedMessages)); |
|||
sessionStorage.setItem(userName + username + 'new', JSON.stringify(storedMessagesNew)); |
|||
console.log("this value stored" + sessionStorage.getItem(userName)) |
|||
console.log("last message time stamp = " + lastMessageTimeStamp); |
|||
console.log(sessionStorage.getItem(userName + '-time')); |
|||
|
|||
} |
|||
chatTextArea.textContent = ''; |
|||
chatAreaNew.innerHTML = ''; |
|||
console.log("Stored messages 2 = " + storedMessages); |
|||
storedMessages.forEach(function(messageLine) { |
|||
chatTextArea.append(messageLine + '\n'); |
|||
chatTextArea.scrollTop = chatTextArea.scrollHeight; |
|||
|
|||
// let context = {message: messageLine};
|
|||
// let msgContainer;
|
|||
// if(obj.fromUser == username)
|
|||
// {
|
|||
// msgContainer = msgContainerSendTemplate(context);
|
|||
// }
|
|||
// else{
|
|||
// msgContainer = msgContainerTemplate(context);
|
|||
// }
|
|||
|
|||
// $(chatAreaNew).append(msgContainer);
|
|||
}) |
|||
|
|||
storedMessagesNew.forEach(function(contextString) { |
|||
let context = JSON.parse(contextString); |
|||
let msgContainer; |
|||
if (context.fromUser == username) { |
|||
msgContainer = msgContainerSendTemplate(context); |
|||
} else { |
|||
msgContainer = msgContainerTemplate(context); |
|||
} |
|||
|
|||
$(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); |
|||
scrollChatAreaAnimated(2400); |
|||
}) |
|||
|
|||
|
|||
}); |
|||
|
|||
|
|||
} |
|||
// chatTextArea.append(JSON.stringify(storedMessages));
|
|||
|
|||
} |
|||
// sessionStorage.setItem('status', 'ready');
|
|||
// sessionStorage.setItem('userName', messageLog);
|
|||
// console.log('Message log = ' + messageLog);
|
|||
// }
|
|||
|
|||
// let passphraseKey = userName + '-passphrase';
|
|||
// sessionStorage.setItem(passphraseKey, passphrase);
|
|||
// console.log(sessionStorage.getItem(passphraseKey));
|
|||
} |
|||
|
|||
// var lastMessageTimeStamp;
|
|||
|
|||
// console.log(authToken);
|
|||
// 'Basic ' + btoa("hmm" + ":" + "hmm")
|
|||
|
|||
Handlebars.registerHelper('avatar', function() { |
|||
return '<div class="img_cont_msg"> <img src="https://static.turbosquid.com/Preview/001292/481/WV/_D.jpg" class="rounded-circle user_img_msg"> </div>'; |
|||
}); |
|||
|
|||
|
|||
// var user;
|
|||
function getSelectedUser() { |
|||
for (var i = 0; i < toUserRadios.length; i++) { |
|||
if (toUserRadios[i].checked) { |
|||
let user = toUserRadios[i].value; |
|||
console.log('sending to user = ' + user); |
|||
isCheckedUser = true; |
|||
return user; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
function getSelectedUserNew() { |
|||
return sessionStorage.getItem('selectedUser'); |
|||
} |
|||
|
|||
document.getElementById('chatMessageForm').addEventListener('submit', function(e) { |
|||
let chatInput = document.getElementById('chatInput'); |
|||
e.preventDefault(); |
|||
let user = getSelectedUserNew(); |
|||
|
|||
if (!this.checkValidity()) { |
|||
console.log("error"); |
|||
this.classList.add('was-validated'); |
|||
return; |
|||
} |
|||
this.classList.add('was-validated'); |
|||
|
|||
if (user == null) { |
|||
// window.alert('please select a user');
|
|||
alertify.error('Please select a user'); |
|||
return; |
|||
} |
|||
let messageContent = chatInput.value; |
|||
let context = { fromUser: username, message: md.render(messageContent), time: new Date().toLocaleString() }; |
|||
let msgContainer = msgContainerSendTemplate(context); |
|||
$(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); |
|||
scrollChatAreaAnimated(2400); |
|||
let messageCipher = sjcl.encrypt(passphraseInput.value, messageContent, { mode: "gcm", ts: 128, adata: "", iter: iterations }); |
|||
let messageCipherJson = JSON.parse(messageCipher); |
|||
let chatMessageDTO = { |
|||
"toUser": user, |
|||
"messageCipher": messageCipherJson |
|||
} |
|||
messageSend(JSON.stringify(chatMessageDTO)); |
|||
}) |
|||
|
|||
document.getElementById('user-search').addEventListener('submit', function(e) { |
|||
e.preventDefault(); |
|||
let contactsBox = document.getElementById('contacts-box'); |
|||
let temp = contactsBox.innerHTML; |
|||
// log.trace(temp);
|
|||
let searchTerm = document.getElementById('user-search-term').value; |
|||
log.debug("search term value = " + searchTerm); |
|||
let list = JSON.parse(sessionStorage.getItem('activeUsers')); |
|||
log.debug("active users"); |
|||
log.debug(list); |
|||
let fuse = new Fuse(list, fuseOptions); |
|||
let searchResult = fuse.search(searchTerm); |
|||
populateContactsBox(contactsBox, searchResult); |
|||
addUserCallBacks(); |
|||
log.debug(searchResult); |
|||
}) |
|||
document.getElementById('user-search-term').addEventListener('input', function(e) { |
|||
e.preventDefault(); |
|||
if (this.value.length < 2) { |
|||
log.debug("inputted") |
|||
let cancelButton = document.getElementById('user-search-cancel'); |
|||
cancelButton.hidden = false; |
|||
} |
|||
}) |
|||
document.getElementById('user-search-cancel').addEventListener('click', function(e) { |
|||
e.preventDefault(); |
|||
let list = JSON.parse(sessionStorage.getItem('activeUsers')); |
|||
let contactsBox = document.getElementById('contacts-box'); |
|||
populateContactsBox(contactsBox,list); |
|||
addUserCallBacks(); |
|||
document.getElementById('user-search-term').value = ""; |
|||
this.hidden = true; |
|||
}) |
|||
|
|||
function populateContactsBox(contactsBox, list) |
|||
{ |
|||
let userContactBoxList = ""; |
|||
list.forEach(function(activeUser) { |
|||
log.debug(activeUser); |
|||
if (activeUser.online) { |
|||
userContactBoxList += userContactOnlineTemplate(activeUser); |
|||
} else { |
|||
userContactBoxList += userContactOfflineTemplate(activeUser); |
|||
} |
|||
}) |
|||
contactsBox.innerHTML = userContactBoxList; |
|||
} |
|||
|
|||
|
|||
|
|||
// console.log('Credentials = ' + JSON.parse(sessionStorage.getItem('credentials')));
|
|||
|
|||
|
|||
function messageSend(chatMessageDTO) { |
|||
let headers = new Headers(); |
|||
// console.log("Token = " + btoa("hmm" + ":" + "hmm"))
|
|||
|
|||
// headers.append('Accept','application/json')
|
|||
headers.append('Content-Type', 'application/json'); |
|||
// headers.append('Authorization', basicAuthToken);
|
|||
headers.append('X-AUTH-TOKEN', authToken); |
|||
fetch(postNewMessageUrl, { |
|||
method: 'POST', |
|||
headers: headers, |
|||
body: chatMessageDTO |
|||
}) |
|||
.then(response => { |
|||
console.log(response); |
|||
return response.clone(); |
|||
}) |
|||
.then(response => fetchHandler(response)); |
|||
} |
|||
|
|||
|
|||
async function getAllMessages(toUser) { |
|||
let headers = new Headers(); |
|||
// headers.append('Accept','application/json')
|
|||
// headers.append('Content-Type', 'application/json');
|
|||
// headers.append('Authorization', basicAuthToken);
|
|||
headers.append('X-AUTH-TOKEN', authToken); |
|||
let response = await fetch(getAllMessagesUrl + toUser, { |
|||
method: 'GET', |
|||
headers: headers |
|||
}); |
|||
console.log(response); |
|||
if (fetchErrorHandler(response.clone())) { |
|||
return null; |
|||
} |
|||
// if (response.status == 440) {
|
|||
// window.alert('Token has expired. Please login again');
|
|||
// return null;
|
|||
// }
|
|||
let data = await response.json(); |
|||
return data; |
|||
} |
|||
|
|||
async function getNewMessages(toUser, lastMessageTimeStamp) { |
|||
let headers = new Headers(); |
|||
// headers.append('Authorization', basicAuthToken);
|
|||
headers.append('X-AUTH-TOKEN', authToken); |
|||
let response = await fetch(`${getNewMessagesUrl}${toUser}/${lastMessageTimeStamp}`, { |
|||
method: 'GET', |
|||
headers: headers |
|||
}); |
|||
console.log(response.clone()); |
|||
if (fetchErrorHandler(response.clone())) { |
|||
return null; |
|||
} |
|||
let data = await response.json(); |
|||
return data; |
|||
} |
|||
|
|||
|
|||
async function getActiveUsers(authToken2) { |
|||
let headers = new Headers(); |
|||
// headers.append('Authorization', basicAuthToken);
|
|||
headers.append('X-AUTH-TOKEN', authToken2); |
|||
let response = await fetch(getActiveUsersUrl, { |
|||
method: 'GET', |
|||
headers: headers |
|||
}); |
|||
console.log(response.clone()); |
|||
if (fetchErrorHandler(response.clone())) { |
|||
return null; |
|||
} |
|||
let data = await response.json(); |
|||
return data; |
|||
} |
|||
|
|||
$(document).ready(function() { |
|||
$('#action_menu_btn').click(function() { |
|||
$('.action_menu').toggle(); |
|||
}); |
|||
}); |
|||
|
|||
function fetchHandler(response) { |
|||
if (response.ok) { |
|||
return response.json().then(json => { |
|||
// the status was ok and there is a json body
|
|||
// return Promise.resolve({ json: json, response: response });
|
|||
alertify.success('Message sent succesfully' + sprintf(" (http code %d)", response.status)); |
|||
}).catch(err => { |
|||
// the status was ok but there is no json body
|
|||
// return Promise.resolve({ response: response });
|
|||
alertify.success('Message sent succesfully' + sprintf(" (http code %d)", response.status)); |
|||
}); |
|||
|
|||
} else { |
|||
return response.json().catch(err => { |
|||
// the status was not ok and there is no json body
|
|||
// throw new Error(response.statusText);
|
|||
alertify.error('Some error occured. Please try again.'); |
|||
}).then(json => { |
|||
// the status was not ok but there is a json body
|
|||
// throw new Error(json.error.message); // example error message returned by a REST
|
|||
let delay = alertify.get('notifier', 'delay'); |
|||
alertify.set('notifier', 'delay', 30); |
|||
let errorMessage = ""; |
|||
json.errors.forEach(function(data) { |
|||
errorMessage += sprintf("Field Name: %s \n Rejected value: %s \n Reason: %s \n", data.field_name, data.rejected_value, data.error_message); |
|||
}); |
|||
alertify.error(sprintf('There were errors in your message - %s', errorMessage)); |
|||
alertify.set('notifier', 'delay', delay); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
|
|||
function fetchErrorHandler(response) { |
|||
// alertify.success('Current position : ' + alertify.get('notifier', 'position'));
|
|||
if (!response.ok) { |
|||
return response.text().catch(err => { |
|||
// the status was not ok and there is no json body
|
|||
// throw new Error(response.statusText);
|
|||
// window.alert(sprintf('Some error occured. Http code is %s', response.status));
|
|||
alertify.error(sprintf('Some error occured. Http code is %s', response.status)); |
|||
return true; |
|||
}).then(json => { |
|||
// the status was not ok but there is a json body
|
|||
// throw new Error(json.error.message); // example error message returned by a REST API
|
|||
// window.alert(sprintf('Error: %s (Http code %s)', json, response.status));
|
|||
alertify.error(sprintf('Some error occured. Http code is %s', response.status)); |
|||
console.log(json); |
|||
return true; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
function scrollChatAreaAnimated(delay) { |
|||
$(chatAreaNew).stop().animate({ |
|||
scrollTop: $(chatAreaNew)[0].scrollHeight |
|||
}, delay); |
|||
} |
@ -0,0 +1 @@ |
|||
../atob/bin/atob.js |
@ -0,0 +1 @@ |
|||
../handlebars/bin/handlebars |
@ -0,0 +1 @@ |
|||
../markdown-it/bin/markdown-it.js |
@ -0,0 +1 @@ |
|||
../mime/cli.js |
@ -0,0 +1 @@ |
|||
../uglify-js/bin/uglifyjs |
@ -0,0 +1 @@ |
|||
../which/bin/which |
@ -0,0 +1,51 @@ |
|||
{ |
|||
"systemParams": "linux-x64-72", |
|||
"modulesFolders": [ |
|||
"node_modules" |
|||
], |
|||
"flags": [], |
|||
"linkedModules": [], |
|||
"topLevelPatterns": [ |
|||
"alertifyjs@^1.12.0", |
|||
"chart.js@^2.9.3", |
|||
"dompurify@^2.0.7", |
|||
"fuse.js@^3.4.6", |
|||
"handlebars@^4.5.3", |
|||
"loglevel@^1.6.6", |
|||
"markdown-it@^10.0.0", |
|||
"sjcl@^1.0.8" |
|||
], |
|||
"lockfileEntries": { |
|||
"alertifyjs@^1.12.0": "https://registry.yarnpkg.com/alertifyjs/-/alertifyjs-1.12.0.tgz#75be1eac23e059d3b990ab076979d36a45aa21ac", |
|||
"argparse@^1.0.7": "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911", |
|||
"chart.js@^2.9.3": "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.3.tgz#ae3884114dafd381bc600f5b35a189138aac1ef7", |
|||
"chartjs-color-string@^0.6.0": "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71", |
|||
"chartjs-color@^2.1.0": "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0", |
|||
"color-convert@^1.9.3": "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8", |
|||
"color-name@1.1.3": "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25", |
|||
"color-name@^1.0.0": "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2", |
|||
"commander@~2.20.3": "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33", |
|||
"dompurify@^2.0.7": "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.7.tgz#f8266ad38fe1602fb5b3222f31eedbf5c16c4fd5", |
|||
"entities@~2.0.0": "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4", |
|||
"fuse.js@^3.4.6": "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.6.tgz#545c3411fed88bf2e27c457cab6e73e7af697a45", |
|||
"handlebars@^4.5.3": "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482", |
|||
"linkify-it@^2.0.0": "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf", |
|||
"loglevel@^1.6.6": "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312", |
|||
"markdown-it@^10.0.0": "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc", |
|||
"mdurl@^1.0.1": "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e", |
|||
"minimist@~0.0.1": "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf", |
|||
"moment@^2.10.2": "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b", |
|||
"neo-async@^2.6.0": "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c", |
|||
"optimist@^0.6.1": "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686", |
|||
"sjcl@^1.0.8": "https://registry.yarnpkg.com/sjcl/-/sjcl-1.0.8.tgz#f2ec8d7dc1f0f21b069b8914a41a8f236b0e252a", |
|||
"source-map@^0.6.1": "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263", |
|||
"source-map@~0.6.1": "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263", |
|||
"sprintf-js@~1.0.2": "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c", |
|||
"uc.micro@^1.0.1": "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac", |
|||
"uc.micro@^1.0.5": "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac", |
|||
"uglify-js@^3.1.4": "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.1.tgz#35c7de17971a4aa7689cd2eae0a5b39bb838c0c5", |
|||
"wordwrap@~0.0.2": "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" |
|||
}, |
|||
"files": [], |
|||
"artifacts": {} |
|||
} |
@ -0,0 +1,38 @@ |
|||
{ |
|||
"boss": true, |
|||
"curly": true, |
|||
"eqeqeq": true, |
|||
"eqnull": true, |
|||
"es5": false, |
|||
"forin": true, |
|||
"immed": true, |
|||
"indent": 4, |
|||
"latedef": true, |
|||
"newcap": true, |
|||
"noarg": true, |
|||
"node": true, |
|||
"noempty": true, |
|||
"plusplus": true, |
|||
"quotmark": "single", |
|||
"smarttabs": false, |
|||
"scripturl": true, |
|||
"strict": false, |
|||
"sub": true, |
|||
"trailing": true, |
|||
"undef": true, |
|||
"unused": true, |
|||
|
|||
"globals": { |
|||
"window": true, |
|||
"document": true, |
|||
"alertify": true, |
|||
"define": true, |
|||
|
|||
"triggerEvent": true, |
|||
"suite": true, |
|||
"test": true, |
|||
"assert": true, |
|||
"setup": true, |
|||
"teardown": true |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
Bugs |
|||
==== |
|||
If you are reporting a bug you must create a test-case. You can fork this [codepen](http://codepen.io/anon/pen/raohK) or this [jsfiddle](http://jsfiddle.net/g2o52zq7/) to get started. |
|||
|
|||
Also include re-produce steps and environement specs, such as OS and Browser (**We support last 2 versions only**). |
|||
|
|||
> Remember, calls to `alertify.alert`, `alertify.confirm` and `alertify.prompt` are none blocking. |
|||
``` |
|||
//bad |
|||
if(alertify.confirm('Are you sure?')){ |
|||
// this would execute immediatly |
|||
} |
|||
//good |
|||
alertify.confirm('Are you sure?', function(){ |
|||
//this would execute when the user clicks ok |
|||
}); |
|||
``` |
|||
|
|||
|
|||
Questions |
|||
==== |
|||
For how-to questions, please post on [stackoverflow](http://stackoverflow.com/questions/tagged/alertifyjs) and don't forget to tag with `alertifyjs`. |
@ -0,0 +1,235 @@ |
|||
module.exports = function (grunt) { |
|||
'use strict'; |
|||
|
|||
// Project configuration.
|
|||
grunt.initConfig({ |
|||
pkg: grunt.file.readJSON('package.json'), |
|||
|
|||
clean: { |
|||
build: ['staging', 'build'] |
|||
}, |
|||
|
|||
usebanner: { |
|||
dist: { |
|||
options: { |
|||
position: 'top', |
|||
banner: '/**\n' + |
|||
' * <%= pkg.name %> <%= pkg.version %> <%= pkg.homepage %>\n' + |
|||
' * <%= pkg.description %>\n' + |
|||
' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %> \n' + |
|||
' * Licensed under <%= pkg.licenses[0].type %> <<%= pkg.licenses[0].url %>>*/\n', |
|||
linebreak: false |
|||
}, |
|||
files: { |
|||
src: ['build/**/*.css'] |
|||
} |
|||
} |
|||
}, |
|||
|
|||
less: { |
|||
options: { |
|||
paths: ['./src/less'], |
|||
compress: false, |
|||
}, |
|||
compile: { |
|||
expand: true, |
|||
cwd: 'src/less', |
|||
src: ['**/*.less'], |
|||
ext: '.css', |
|||
dest: 'staging' |
|||
} |
|||
}, |
|||
|
|||
postcss: { |
|||
options: { |
|||
map: false, |
|||
processors: [ |
|||
require('autoprefixer')({browsers: 'last 2 versions'}), |
|||
] |
|||
}, |
|||
build: { |
|||
expand: true, |
|||
cwd: 'staging/', |
|||
dest: 'staging/', |
|||
src: ['**/*.css'], |
|||
}, |
|||
}, |
|||
|
|||
rtlcss: { |
|||
prefixRules: { |
|||
options: { |
|||
rules: [ |
|||
{ |
|||
'name': 'prefix', |
|||
'expr': /.*/img, |
|||
'important': true, |
|||
'action': function (rule) { |
|||
//prefix rules with ajs- and ignore further processing
|
|||
rule.selector = rule.selector.replace(/\.(?!alertify)/g, '.ajs-'); |
|||
return true; |
|||
} |
|||
} |
|||
] |
|||
}, |
|||
expand: true, |
|||
cwd: 'staging', |
|||
src: ['**/*.css'], |
|||
dest: 'staging', |
|||
}, |
|||
build: { |
|||
expand : true, |
|||
cwd: 'staging', |
|||
src: ['**/*.css'], |
|||
dest: 'staging/rtl', |
|||
ext: '.css', |
|||
} |
|||
}, |
|||
|
|||
cssmin: { |
|||
options: { |
|||
report: 'gzip' |
|||
}, |
|||
min: { |
|||
expand:true, |
|||
cwd:'staging', |
|||
src:['*.css', 'themes/*.css'], |
|||
dest:'build/css', |
|||
ext: '.min.css', |
|||
}, |
|||
rtl: { |
|||
expand:true, |
|||
cwd:'staging/rtl', |
|||
src:['**/*.css'], |
|||
dest:'build/css', |
|||
ext: '.rtl.min.css', |
|||
} |
|||
}, |
|||
|
|||
copy: { |
|||
ltr:{ |
|||
expand:true, |
|||
cwd:'staging', |
|||
src:['*.css', 'themes/*.css'], |
|||
dest:'build/css', |
|||
ext:'.css' |
|||
}, |
|||
rtl:{ |
|||
expand:true, |
|||
cwd:'staging/rtl', |
|||
src:['**/*.css'], |
|||
dest:'build/css', |
|||
ext:'.rtl.css' |
|||
}, |
|||
build:{ |
|||
expand:true, |
|||
cwd:'build', |
|||
src:['**'], |
|||
dest:'docpad/files/build' |
|||
} |
|||
}, |
|||
|
|||
concat: { |
|||
options: { |
|||
stripBanners: false, |
|||
banner: '/**\n' + |
|||
' * <%= pkg.name %> <%= pkg.version %> <%= pkg.homepage %>\n' + |
|||
' * <%= pkg.description %>\n' + |
|||
' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %> \n' + |
|||
' * Licensed under <%= pkg.licenses[0].type %> <<%= pkg.licenses[0].url %>>*/\n', |
|||
}, |
|||
dist: { |
|||
src: [ |
|||
'src/js/intro.js', |
|||
'src/js/event.js', |
|||
|
|||
'src/js/dialog/intro.js', |
|||
'src/js/dialog/commands.js', |
|||
'src/js/dialog/actions.js', |
|||
'src/js/dialog/focus.js', |
|||
'src/js/dialog/transition.js', |
|||
'src/js/dialog/move.js', |
|||
'src/js/dialog/resize.js', |
|||
'src/js/dialog/events.js', |
|||
'src/js/dialog/dialog.js', |
|||
'src/js/dialog/outro.js', |
|||
|
|||
'src/js/notifier.js', |
|||
'src/js/alertify.js', |
|||
'src/js/alert.js', |
|||
'src/js/confirm.js', |
|||
'src/js/prompt.js', |
|||
'src/js/outro.js' |
|||
], |
|||
dest: 'build/alertify.js' |
|||
} |
|||
}, |
|||
|
|||
|
|||
jshint: { |
|||
files: { |
|||
src: [ |
|||
'Gruntfile.js', |
|||
'build/alertify.js', |
|||
'test/specs/*.js' |
|||
] |
|||
}, |
|||
options: { |
|||
jshintrc: '.jshintrc' |
|||
} |
|||
}, |
|||
|
|||
uglify: { |
|||
options: { |
|||
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + |
|||
'<%= pkg.author %> */\n', |
|||
report: 'gzip' |
|||
}, |
|||
dist: { |
|||
files: { |
|||
'build/alertify.min.js': ['<banner>', 'build/alertify.js'] |
|||
} |
|||
} |
|||
}, |
|||
|
|||
watch: { |
|||
src: { |
|||
files: ['src/**/*.js'], |
|||
tasks: ['build'] |
|||
} |
|||
}, |
|||
|
|||
compress: { |
|||
options: { |
|||
archive: 'build/alertifyjs.zip' |
|||
}, |
|||
build: { |
|||
files: [ |
|||
{ |
|||
expand:true, |
|||
cwd: 'build', |
|||
src: ['**'] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
}); |
|||
|
|||
grunt.loadNpmTasks('grunt-rtlcss'); |
|||
grunt.loadNpmTasks('grunt-postcss'); |
|||
grunt.loadNpmTasks('grunt-contrib-less'); |
|||
grunt.loadNpmTasks('grunt-contrib-clean'); |
|||
grunt.loadNpmTasks('grunt-contrib-concat'); |
|||
grunt.loadNpmTasks('grunt-contrib-connect'); |
|||
grunt.loadNpmTasks('grunt-contrib-jshint'); |
|||
grunt.loadNpmTasks('grunt-contrib-uglify'); |
|||
grunt.loadNpmTasks('grunt-contrib-cssmin'); |
|||
grunt.loadNpmTasks('grunt-contrib-copy'); |
|||
grunt.loadNpmTasks('grunt-contrib-watch'); |
|||
grunt.loadNpmTasks('grunt-contrib-compress'); |
|||
grunt.loadNpmTasks('grunt-banner'); |
|||
|
|||
// Default task
|
|||
grunt.registerTask('css', ['less', 'postcss:build', 'rtlcss', 'copy:rtl', 'copy:ltr', 'cssmin', 'usebanner']); |
|||
grunt.registerTask('build', ['clean:build', 'css', 'concat', 'uglify', 'compress', 'copy:build']); |
|||
grunt.registerTask('default', ['build', 'jshint']); |
|||
}; |
@ -0,0 +1,674 @@ |
|||
GNU GENERAL PUBLIC LICENSE |
|||
Version 3, 29 June 2007 |
|||
|
|||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
|||
Everyone is permitted to copy and distribute verbatim copies |
|||
of this license document, but changing it is not allowed. |
|||
|
|||
Preamble |
|||
|
|||
The GNU General Public License is a free, copyleft license for |
|||
software and other kinds of works. |
|||
|
|||
The licenses for most software and other practical works are designed |
|||
to take away your freedom to share and change the works. By contrast, |
|||
the GNU General Public License is intended to guarantee your freedom to |
|||
share and change all versions of a program--to make sure it remains free |
|||
software for all its users. We, the Free Software Foundation, use the |
|||
GNU General Public License for most of our software; it applies also to |
|||
any other work released this way by its authors. You can apply it to |
|||
your programs, too. |
|||
|
|||
When we speak of free software, we are referring to freedom, not |
|||
price. Our General Public Licenses are designed to make sure that you |
|||
have the freedom to distribute copies of free software (and charge for |
|||
them if you wish), that you receive source code or can get it if you |
|||
want it, that you can change the software or use pieces of it in new |
|||
free programs, and that you know you can do these things. |
|||
|
|||
To protect your rights, we need to prevent others from denying you |
|||
these rights or asking you to surrender the rights. Therefore, you have |
|||
certain responsibilities if you distribute copies of the software, or if |
|||
you modify it: responsibilities to respect the freedom of others. |
|||
|
|||
For example, if you distribute copies of such a program, whether |
|||
gratis or for a fee, you must pass on to the recipients the same |
|||
freedoms that you received. You must make sure that they, too, receive |
|||
or can get the source code. And you must show them these terms so they |
|||
know their rights. |
|||
|
|||
Developers that use the GNU GPL protect your rights with two steps: |
|||
(1) assert copyright on the software, and (2) offer you this License |
|||
giving you legal permission to copy, distribute and/or modify it. |
|||
|
|||
For the developers' and authors' protection, the GPL clearly explains |
|||
that there is no warranty for this free software. For both users' and |
|||
authors' sake, the GPL requires that modified versions be marked as |
|||
changed, so that their problems will not be attributed erroneously to |
|||
authors of previous versions. |
|||
|
|||
Some devices are designed to deny users access to install or run |
|||
modified versions of the software inside them, although the manufacturer |
|||
can do so. This is fundamentally incompatible with the aim of |
|||
protecting users' freedom to change the software. The systematic |
|||
pattern of such abuse occurs in the area of products for individuals to |
|||
use, which is precisely where it is most unacceptable. Therefore, we |
|||
have designed this version of the GPL to prohibit the practice for those |
|||
products. If such problems arise substantially in other domains, we |
|||
stand ready to extend this provision to those domains in future versions |
|||
of the GPL, as needed to protect the freedom of users. |
|||
|
|||
Finally, every program is threatened constantly by software patents. |
|||
States should not allow patents to restrict development and use of |
|||
software on general-purpose computers, but in those that do, we wish to |
|||
avoid the special danger that patents applied to a free program could |
|||
make it effectively proprietary. To prevent this, the GPL assures that |
|||
patents cannot be used to render the program non-free. |
|||
|
|||
The precise terms and conditions for copying, distribution and |
|||
modification follow. |
|||
|
|||
TERMS AND CONDITIONS |
|||
|
|||
0. Definitions. |
|||
|
|||
"This License" refers to version 3 of the GNU General Public License. |
|||
|
|||
"Copyright" also means copyright-like laws that apply to other kinds of |
|||
works, such as semiconductor masks. |
|||
|
|||
"The Program" refers to any copyrightable work licensed under this |
|||
License. Each licensee is addressed as "you". "Licensees" and |
|||
"recipients" may be individuals or organizations. |
|||
|
|||
To "modify" a work means to copy from or adapt all or part of the work |
|||
in a fashion requiring copyright permission, other than the making of an |
|||
exact copy. The resulting work is called a "modified version" of the |
|||
earlier work or a work "based on" the earlier work. |
|||
|
|||
A "covered work" means either the unmodified Program or a work based |
|||
on the Program. |
|||
|
|||
To "propagate" a work means to do anything with it that, without |
|||
permission, would make you directly or secondarily liable for |
|||
infringement under applicable copyright law, except executing it on a |
|||
computer or modifying a private copy. Propagation includes copying, |
|||
distribution (with or without modification), making available to the |
|||
public, and in some countries other activities as well. |
|||
|
|||
To "convey" a work means any kind of propagation that enables other |
|||
parties to make or receive copies. Mere interaction with a user through |
|||
a computer network, with no transfer of a copy, is not conveying. |
|||
|
|||
An interactive user interface displays "Appropriate Legal Notices" |
|||
to the extent that it includes a convenient and prominently visible |
|||
feature that (1) displays an appropriate copyright notice, and (2) |
|||
tells the user that there is no warranty for the work (except to the |
|||
extent that warranties are provided), that licensees may convey the |
|||
work under this License, and how to view a copy of this License. If |
|||
the interface presents a list of user commands or options, such as a |
|||
menu, a prominent item in the list meets this criterion. |
|||
|
|||
1. Source Code. |
|||
|
|||
The "source code" for a work means the preferred form of the work |
|||
for making modifications to it. "Object code" means any non-source |
|||
form of a work. |
|||
|
|||
A "Standard Interface" means an interface that either is an official |
|||
standard defined by a recognized standards body, or, in the case of |
|||
interfaces specified for a particular programming language, one that |
|||
is widely used among developers working in that language. |
|||
|
|||
The "System Libraries" of an executable work include anything, other |
|||
than the work as a whole, that (a) is included in the normal form of |
|||
packaging a Major Component, but which is not part of that Major |
|||
Component, and (b) serves only to enable use of the work with that |
|||
Major Component, or to implement a Standard Interface for which an |
|||
implementation is available to the public in source code form. A |
|||
"Major Component", in this context, means a major essential component |
|||
(kernel, window system, and so on) of the specific operating system |
|||
(if any) on which the executable work runs, or a compiler used to |
|||
produce the work, or an object code interpreter used to run it. |
|||
|
|||
The "Corresponding Source" for a work in object code form means all |
|||
the source code needed to generate, install, and (for an executable |
|||
work) run the object code and to modify the work, including scripts to |
|||
control those activities. However, it does not include the work's |
|||
System Libraries, or general-purpose tools or generally available free |
|||
programs which are used unmodified in performing those activities but |
|||
which are not part of the work. For example, Corresponding Source |
|||
includes interface definition files associated with source files for |
|||
the work, and the source code for shared libraries and dynamically |
|||
linked subprograms that the work is specifically designed to require, |
|||
such as by intimate data communication or control flow between those |
|||
subprograms and other parts of the work. |
|||
|
|||
The Corresponding Source need not include anything that users |
|||
can regenerate automatically from other parts of the Corresponding |
|||
Source. |
|||
|
|||
The Corresponding Source for a work in source code form is that |
|||
same work. |
|||
|
|||
2. Basic Permissions. |
|||
|
|||
All rights granted under this License are granted for the term of |
|||
copyright on the Program, and are irrevocable provided the stated |
|||
conditions are met. This License explicitly affirms your unlimited |
|||
permission to run the unmodified Program. The output from running a |
|||
covered work is covered by this License only if the output, given its |
|||
content, constitutes a covered work. This License acknowledges your |
|||
rights of fair use or other equivalent, as provided by copyright law. |
|||
|
|||
You may make, run and propagate covered works that you do not |
|||
convey, without conditions so long as your license otherwise remains |
|||
in force. You may convey covered works to others for the sole purpose |
|||
of having them make modifications exclusively for you, or provide you |
|||
with facilities for running those works, provided that you comply with |
|||
the terms of this License in conveying all material for which you do |
|||
not control copyright. Those thus making or running the covered works |
|||
for you must do so exclusively on your behalf, under your direction |
|||
and control, on terms that prohibit them from making any copies of |
|||
your copyrighted material outside their relationship with you. |
|||
|
|||
Conveying under any other circumstances is permitted solely under |
|||
the conditions stated below. Sublicensing is not allowed; section 10 |
|||
makes it unnecessary. |
|||
|
|||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
|||
|
|||
No covered work shall be deemed part of an effective technological |
|||
measure under any applicable law fulfilling obligations under article |
|||
11 of the WIPO copyright treaty adopted on 20 December 1996, or |
|||
similar laws prohibiting or restricting circumvention of such |
|||
measures. |
|||
|
|||
When you convey a covered work, you waive any legal power to forbid |
|||
circumvention of technological measures to the extent such circumvention |
|||
is effected by exercising rights under this License with respect to |
|||
the covered work, and you disclaim any intention to limit operation or |
|||
modification of the work as a means of enforcing, against the work's |
|||
users, your or third parties' legal rights to forbid circumvention of |
|||
technological measures. |
|||
|
|||
4. Conveying Verbatim Copies. |
|||
|
|||
You may convey verbatim copies of the Program's source code as you |
|||
receive it, in any medium, provided that you conspicuously and |
|||
appropriately publish on each copy an appropriate copyright notice; |
|||
keep intact all notices stating that this License and any |
|||
non-permissive terms added in accord with section 7 apply to the code; |
|||
keep intact all notices of the absence of any warranty; and give all |
|||
recipients a copy of this License along with the Program. |
|||
|
|||
You may charge any price or no price for each copy that you convey, |
|||
and you may offer support or warranty protection for a fee. |
|||
|
|||
5. Conveying Modified Source Versions. |
|||
|
|||
You may convey a work based on the Program, or the modifications to |
|||
produce it from the Program, in the form of source code under the |
|||
terms of section 4, provided that you also meet all of these conditions: |
|||
|
|||
a) The work must carry prominent notices stating that you modified |
|||
it, and giving a relevant date. |
|||
|
|||
b) The work must carry prominent notices stating that it is |
|||
released under this License and any conditions added under section |
|||
7. This requirement modifies the requirement in section 4 to |
|||
"keep intact all notices". |
|||
|
|||
c) You must license the entire work, as a whole, under this |
|||
License to anyone who comes into possession of a copy. This |
|||
License will therefore apply, along with any applicable section 7 |
|||
additional terms, to the whole of the work, and all its parts, |
|||
regardless of how they are packaged. This License gives no |
|||
permission to license the work in any other way, but it does not |
|||
invalidate such permission if you have separately received it. |
|||
|
|||
d) If the work has interactive user interfaces, each must display |
|||
Appropriate Legal Notices; however, if the Program has interactive |
|||
interfaces that do not display Appropriate Legal Notices, your |
|||
work need not make them do so. |
|||
|
|||
A compilation of a covered work with other separate and independent |
|||
works, which are not by their nature extensions of the covered work, |
|||
and which are not combined with it such as to form a larger program, |
|||
in or on a volume of a storage or distribution medium, is called an |
|||
"aggregate" if the compilation and its resulting copyright are not |
|||
used to limit the access or legal rights of the compilation's users |
|||
beyond what the individual works permit. Inclusion of a covered work |
|||
in an aggregate does not cause this License to apply to the other |
|||
parts of the aggregate. |
|||
|
|||
6. Conveying Non-Source Forms. |
|||
|
|||
You may convey a covered work in object code form under the terms |
|||
of sections 4 and 5, provided that you also convey the |
|||
machine-readable Corresponding Source under the terms of this License, |
|||
in one of these ways: |
|||
|
|||
a) Convey the object code in, or embodied in, a physical product |
|||
(including a physical distribution medium), accompanied by the |
|||
Corresponding Source fixed on a durable physical medium |
|||
customarily used for software interchange. |
|||
|
|||
b) Convey the object code in, or embodied in, a physical product |
|||
(including a physical distribution medium), accompanied by a |
|||
written offer, valid for at least three years and valid for as |
|||
long as you offer spare parts or customer support for that product |
|||
model, to give anyone who possesses the object code either (1) a |
|||
copy of the Corresponding Source for all the software in the |
|||
product that is covered by this License, on a durable physical |
|||
medium customarily used for software interchange, for a price no |
|||
more than your reasonable cost of physically performing this |
|||
conveying of source, or (2) access to copy the |
|||
Corresponding Source from a network server at no charge. |
|||
|
|||
c) Convey individual copies of the object code with a copy of the |
|||
written offer to provide the Corresponding Source. This |
|||
alternative is allowed only occasionally and noncommercially, and |
|||
only if you received the object code with such an offer, in accord |
|||
with subsection 6b. |
|||
|
|||
d) Convey the object code by offering access from a designated |
|||
place (gratis or for a charge), and offer equivalent access to the |
|||
Corresponding Source in the same way through the same place at no |
|||
further charge. You need not require recipients to copy the |
|||
Corresponding Source along with the object code. If the place to |
|||
copy the object code is a network server, the Corresponding Source |
|||
may be on a different server (operated by you or a third party) |
|||
that supports equivalent copying facilities, provided you maintain |
|||
clear directions next to the object code saying where to find the |
|||
Corresponding Source. Regardless of what server hosts the |
|||
Corresponding Source, you remain obligated to ensure that it is |
|||
available for as long as needed to satisfy these requirements. |
|||
|
|||
e) Convey the object code using peer-to-peer transmission, provided |
|||
you inform other peers where the object code and Corresponding |
|||
Source of the work are being offered to the general public at no |
|||
charge under subsection 6d. |
|||
|
|||
A separable portion of the object code, whose source code is excluded |
|||
from the Corresponding Source as a System Library, need not be |
|||
included in conveying the object code work. |
|||
|
|||
A "User Product" is either (1) a "consumer product", which means any |
|||
tangible personal property which is normally used for personal, family, |
|||
or household purposes, or (2) anything designed or sold for incorporation |
|||
into a dwelling. In determining whether a product is a consumer product, |
|||
doubtful cases shall be resolved in favor of coverage. For a particular |
|||
product received by a particular user, "normally used" refers to a |
|||
typical or common use of that class of product, regardless of the status |
|||
of the particular user or of the way in which the particular user |
|||
actually uses, or expects or is expected to use, the product. A product |
|||
is a consumer product regardless of whether the product has substantial |
|||
commercial, industrial or non-consumer uses, unless such uses represent |
|||
the only significant mode of use of the product. |
|||
|
|||
"Installation Information" for a User Product means any methods, |
|||
procedures, authorization keys, or other information required to install |
|||
and execute modified versions of a covered work in that User Product from |
|||
a modified version of its Corresponding Source. The information must |
|||
suffice to ensure that the continued functioning of the modified object |
|||
code is in no case prevented or interfered with solely because |
|||
modification has been made. |
|||
|
|||
If you convey an object code work under this section in, or with, or |
|||
specifically for use in, a User Product, and the conveying occurs as |
|||
part of a transaction in which the right of possession and use of the |
|||
User Product is transferred to the recipient in perpetuity or for a |
|||
fixed term (regardless of how the transaction is characterized), the |
|||
Corresponding Source conveyed under this section must be accompanied |
|||
by the Installation Information. But this requirement does not apply |
|||
if neither you nor any third party retains the ability to install |
|||
modified object code on the User Product (for example, the work has |
|||
been installed in ROM). |
|||
|
|||
The requirement to provide Installation Information does not include a |
|||
requirement to continue to provide support service, warranty, or updates |
|||
for a work that has been modified or installed by the recipient, or for |
|||
the User Product in which it has been modified or installed. Access to a |
|||
network may be denied when the modification itself materially and |
|||
adversely affects the operation of the network or violates the rules and |
|||
protocols for communication across the network. |
|||
|
|||
Corresponding Source conveyed, and Installation Information provided, |
|||
in accord with this section must be in a format that is publicly |
|||
documented (and with an implementation available to the public in |
|||
source code form), and must require no special password or key for |
|||
unpacking, reading or copying. |
|||
|
|||
7. Additional Terms. |
|||
|
|||
"Additional permissions" are terms that supplement the terms of this |
|||
License by making exceptions from one or more of its conditions. |
|||
Additional permissions that are applicable to the entire Program shall |
|||
be treated as though they were included in this License, to the extent |
|||
that they are valid under applicable law. If additional permissions |
|||
apply only to part of the Program, that part may be used separately |
|||
under those permissions, but the entire Program remains governed by |
|||
this License without regard to the additional permissions. |
|||
|
|||
When you convey a copy of a covered work, you may at your option |
|||
remove any additional permissions from that copy, or from any part of |
|||
it. (Additional permissions may be written to require their own |
|||
removal in certain cases when you modify the work.) You may place |
|||
additional permissions on material, added by you to a covered work, |
|||
for which you have or can give appropriate copyright permission. |
|||
|
|||
Notwithstanding any other provision of this License, for material you |
|||
add to a covered work, you may (if authorized by the copyright holders of |
|||
that material) supplement the terms of this License with terms: |
|||
|
|||
a) Disclaiming warranty or limiting liability differently from the |
|||
terms of sections 15 and 16 of this License; or |
|||
|
|||
b) Requiring preservation of specified reasonable legal notices or |
|||
author attributions in that material or in the Appropriate Legal |
|||
Notices displayed by works containing it; or |
|||
|
|||
c) Prohibiting misrepresentation of the origin of that material, or |
|||
requiring that modified versions of such material be marked in |
|||
reasonable ways as different from the original version; or |
|||
|
|||
d) Limiting the use for publicity purposes of names of licensors or |
|||
authors of the material; or |
|||
|
|||
e) Declining to grant rights under trademark law for use of some |
|||
trade names, trademarks, or service marks; or |
|||
|
|||
f) Requiring indemnification of licensors and authors of that |
|||
material by anyone who conveys the material (or modified versions of |
|||
it) with contractual assumptions of liability to the recipient, for |
|||
any liability that these contractual assumptions directly impose on |
|||
those licensors and authors. |
|||
|
|||
All other non-permissive additional terms are considered "further |
|||
restrictions" within the meaning of section 10. If the Program as you |
|||
received it, or any part of it, contains a notice stating that it is |
|||
governed by this License along with a term that is a further |
|||
restriction, you may remove that term. If a license document contains |
|||
a further restriction but permits relicensing or conveying under this |
|||
License, you may add to a covered work material governed by the terms |
|||
of that license document, provided that the further restriction does |
|||
not survive such relicensing or conveying. |
|||
|
|||
If you add terms to a covered work in accord with this section, you |
|||
must place, in the relevant source files, a statement of the |
|||
additional terms that apply to those files, or a notice indicating |
|||
where to find the applicable terms. |
|||
|
|||
Additional terms, permissive or non-permissive, may be stated in the |
|||
form of a separately written license, or stated as exceptions; |
|||
the above requirements apply either way. |
|||
|
|||
8. Termination. |
|||
|
|||
You may not propagate or modify a covered work except as expressly |
|||
provided under this License. Any attempt otherwise to propagate or |
|||
modify it is void, and will automatically terminate your rights under |
|||
this License (including any patent licenses granted under the third |
|||
paragraph of section 11). |
|||
|
|||
However, if you cease all violation of this License, then your |
|||
license from a particular copyright holder is reinstated (a) |
|||
provisionally, unless and until the copyright holder explicitly and |
|||
finally terminates your license, and (b) permanently, if the copyright |
|||
holder fails to notify you of the violation by some reasonable means |
|||
prior to 60 days after the cessation. |
|||
|
|||
Moreover, your license from a particular copyright holder is |
|||
reinstated permanently if the copyright holder notifies you of the |
|||
violation by some reasonable means, this is the first time you have |
|||
received notice of violation of this License (for any work) from that |
|||
copyright holder, and you cure the violation prior to 30 days after |
|||
your receipt of the notice. |
|||
|
|||
Termination of your rights under this section does not terminate the |
|||
licenses of parties who have received copies or rights from you under |
|||
this License. If your rights have been terminated and not permanently |
|||
reinstated, you do not qualify to receive new licenses for the same |
|||
material under section 10. |
|||
|
|||
9. Acceptance Not Required for Having Copies. |
|||
|
|||
You are not required to accept this License in order to receive or |
|||
run a copy of the Program. Ancillary propagation of a covered work |
|||
occurring solely as a consequence of using peer-to-peer transmission |
|||
to receive a copy likewise does not require acceptance. However, |
|||
nothing other than this License grants you permission to propagate or |
|||
modify any covered work. These actions infringe copyright if you do |
|||
not accept this License. Therefore, by modifying or propagating a |
|||
covered work, you indicate your acceptance of this License to do so. |
|||
|
|||
10. Automatic Licensing of Downstream Recipients. |
|||
|
|||
Each time you convey a covered work, the recipient automatically |
|||
receives a license from the original licensors, to run, modify and |
|||
propagate that work, subject to this License. You are not responsible |
|||
for enforcing compliance by third parties with this License. |
|||
|
|||
An "entity transaction" is a transaction transferring control of an |
|||
organization, or substantially all assets of one, or subdividing an |
|||
organization, or merging organizations. If propagation of a covered |
|||
work results from an entity transaction, each party to that |
|||
transaction who receives a copy of the work also receives whatever |
|||
licenses to the work the party's predecessor in interest had or could |
|||
give under the previous paragraph, plus a right to possession of the |
|||
Corresponding Source of the work from the predecessor in interest, if |
|||
the predecessor has it or can get it with reasonable efforts. |
|||
|
|||
You may not impose any further restrictions on the exercise of the |
|||
rights granted or affirmed under this License. For example, you may |
|||
not impose a license fee, royalty, or other charge for exercise of |
|||
rights granted under this License, and you may not initiate litigation |
|||
(including a cross-claim or counterclaim in a lawsuit) alleging that |
|||
any patent claim is infringed by making, using, selling, offering for |
|||
sale, or importing the Program or any portion of it. |
|||
|
|||
11. Patents. |
|||
|
|||
A "contributor" is a copyright holder who authorizes use under this |
|||
License of the Program or a work on which the Program is based. The |
|||
work thus licensed is called the contributor's "contributor version". |
|||
|
|||
A contributor's "essential patent claims" are all patent claims |
|||
owned or controlled by the contributor, whether already acquired or |
|||
hereafter acquired, that would be infringed by some manner, permitted |
|||
by this License, of making, using, or selling its contributor version, |
|||
but do not include claims that would be infringed only as a |
|||
consequence of further modification of the contributor version. For |
|||
purposes of this definition, "control" includes the right to grant |
|||
patent sublicenses in a manner consistent with the requirements of |
|||
this License. |
|||
|
|||
Each contributor grants you a non-exclusive, worldwide, royalty-free |
|||
patent license under the contributor's essential patent claims, to |
|||
make, use, sell, offer for sale, import and otherwise run, modify and |
|||
propagate the contents of its contributor version. |
|||
|
|||
In the following three paragraphs, a "patent license" is any express |
|||
agreement or commitment, however denominated, not to enforce a patent |
|||
(such as an express permission to practice a patent or covenant not to |
|||
sue for patent infringement). To "grant" such a patent license to a |
|||
party means to make such an agreement or commitment not to enforce a |
|||
patent against the party. |
|||
|
|||
If you convey a covered work, knowingly relying on a patent license, |
|||
and the Corresponding Source of the work is not available for anyone |
|||
to copy, free of charge and under the terms of this License, through a |
|||
publicly available network server or other readily accessible means, |
|||
then you must either (1) cause the Corresponding Source to be so |
|||
available, or (2) arrange to deprive yourself of the benefit of the |
|||
patent license for this particular work, or (3) arrange, in a manner |
|||
consistent with the requirements of this License, to extend the patent |
|||
license to downstream recipients. "Knowingly relying" means you have |
|||
actual knowledge that, but for the patent license, your conveying the |
|||
covered work in a country, or your recipient's use of the covered work |
|||
in a country, would infringe one or more identifiable patents in that |
|||
country that you have reason to believe are valid. |
|||
|
|||
If, pursuant to or in connection with a single transaction or |
|||
arrangement, you convey, or propagate by procuring conveyance of, a |
|||
covered work, and grant a patent license to some of the parties |
|||
receiving the covered work authorizing them to use, propagate, modify |
|||
or convey a specific copy of the covered work, then the patent license |
|||
you grant is automatically extended to all recipients of the covered |
|||
work and works based on it. |
|||
|
|||
A patent license is "discriminatory" if it does not include within |
|||
the scope of its coverage, prohibits the exercise of, or is |
|||
conditioned on the non-exercise of one or more of the rights that are |
|||
specifically granted under this License. You may not convey a covered |
|||
work if you are a party to an arrangement with a third party that is |
|||
in the business of distributing software, under which you make payment |
|||
to the third party based on the extent of your activity of conveying |
|||
the work, and under which the third party grants, to any of the |
|||
parties who would receive the covered work from you, a discriminatory |
|||
patent license (a) in connection with copies of the covered work |
|||
conveyed by you (or copies made from those copies), or (b) primarily |
|||
for and in connection with specific products or compilations that |
|||
contain the covered work, unless you entered into that arrangement, |
|||
or that patent license was granted, prior to 28 March 2007. |
|||
|
|||
Nothing in this License shall be construed as excluding or limiting |
|||
any implied license or other defenses to infringement that may |
|||
otherwise be available to you under applicable patent law. |
|||
|
|||
12. No Surrender of Others' Freedom. |
|||
|
|||
If conditions are imposed on you (whether by court order, agreement or |
|||
otherwise) that contradict the conditions of this License, they do not |
|||
excuse you from the conditions of this License. If you cannot convey a |
|||
covered work so as to satisfy simultaneously your obligations under this |
|||
License and any other pertinent obligations, then as a consequence you may |
|||
not convey it at all. For example, if you agree to terms that obligate you |
|||
to collect a royalty for further conveying from those to whom you convey |
|||
the Program, the only way you could satisfy both those terms and this |
|||
License would be to refrain entirely from conveying the Program. |
|||
|
|||
13. Use with the GNU Affero General Public License. |
|||
|
|||
Notwithstanding any other provision of this License, you have |
|||
permission to link or combine any covered work with a work licensed |
|||
under version 3 of the GNU Affero General Public License into a single |
|||
combined work, and to convey the resulting work. The terms of this |
|||
License will continue to apply to the part which is the covered work, |
|||
but the special requirements of the GNU Affero General Public License, |
|||
section 13, concerning interaction through a network will apply to the |
|||
combination as such. |
|||
|
|||
14. Revised Versions of this License. |
|||
|
|||
The Free Software Foundation may publish revised and/or new versions of |
|||
the GNU General Public License from time to time. Such new versions will |
|||
be similar in spirit to the present version, but may differ in detail to |
|||
address new problems or concerns. |
|||
|
|||
Each version is given a distinguishing version number. If the |
|||
Program specifies that a certain numbered version of the GNU General |
|||
Public License "or any later version" applies to it, you have the |
|||
option of following the terms and conditions either of that numbered |
|||
version or of any later version published by the Free Software |
|||
Foundation. If the Program does not specify a version number of the |
|||
GNU General Public License, you may choose any version ever published |
|||
by the Free Software Foundation. |
|||
|
|||
If the Program specifies that a proxy can decide which future |
|||
versions of the GNU General Public License can be used, that proxy's |
|||
public statement of acceptance of a version permanently authorizes you |
|||
to choose that version for the Program. |
|||
|
|||
Later license versions may give you additional or different |
|||
permissions. However, no additional obligations are imposed on any |
|||
author or copyright holder as a result of your choosing to follow a |
|||
later version. |
|||
|
|||
15. Disclaimer of Warranty. |
|||
|
|||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY |
|||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT |
|||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY |
|||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, |
|||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM |
|||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF |
|||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
|||
|
|||
16. Limitation of Liability. |
|||
|
|||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
|||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS |
|||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY |
|||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE |
|||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF |
|||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD |
|||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), |
|||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF |
|||
SUCH DAMAGES. |
|||
|
|||
17. Interpretation of Sections 15 and 16. |
|||
|
|||
If the disclaimer of warranty and limitation of liability provided |
|||
above cannot be given local legal effect according to their terms, |
|||
reviewing courts shall apply local law that most closely approximates |
|||
an absolute waiver of all civil liability in connection with the |
|||
Program, unless a warranty or assumption of liability accompanies a |
|||
copy of the Program in return for a fee. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
How to Apply These Terms to Your New Programs |
|||
|
|||
If you develop a new program, and you want it to be of the greatest |
|||
possible use to the public, the best way to achieve this is to make it |
|||
free software which everyone can redistribute and change under these terms. |
|||
|
|||
To do so, attach the following notices to the program. It is safest |
|||
to attach them to the start of each source file to most effectively |
|||
state the exclusion of warranty; and each file should have at least |
|||
the "copyright" line and a pointer to where the full notice is found. |
|||
|
|||
{one line to give the program's name and a brief idea of what it does.} |
|||
Copyright (C) {year} {name of author} |
|||
|
|||
This program is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
|
|||
Also add information on how to contact you by electronic and paper mail. |
|||
|
|||
If the program does terminal interaction, make it output a short |
|||
notice like this when it starts in an interactive mode: |
|||
|
|||
{project} Copyright (C) {year} {fullname} |
|||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
|||
This is free software, and you are welcome to redistribute it |
|||
under certain conditions; type `show c' for details. |
|||
|
|||
The hypothetical commands `show w' and `show c' should show the appropriate |
|||
parts of the General Public License. Of course, your program's commands |
|||
might be different; for a GUI interface, you would use an "about box". |
|||
|
|||
You should also get your employer (if you work as a programmer) or school, |
|||
if any, to sign a "copyright disclaimer" for the program, if necessary. |
|||
For more information on this, and how to apply and follow the GNU GPL, see |
|||
<http://www.gnu.org/licenses/>. |
|||
|
|||
The GNU General Public License does not permit incorporating your program |
|||
into proprietary programs. If your program is a subroutine library, you |
|||
may consider it more useful to permit linking proprietary applications with |
|||
the library. If this is what you want to do, use the GNU Lesser General |
|||
Public License instead of this License. But first, please read |
|||
<http://www.gnu.org/philosophy/why-not-lgpl.html>. |
@ -0,0 +1,85 @@ |
|||
[![GitHub version](https://badge.fury.io/gh/MohammadYounes%2FAlertifyJS.svg)](http://badge.fury.io/gh/MohammadYounes%2FAlertifyJS) |
|||
[![NuGet version](https://badge.fury.io/nu/AlertifyJS.svg)](http://badge.fury.io/nu/AlertifyJS) |
|||
[![npm version](https://badge.fury.io/js/alertifyjs.svg)](http://badge.fury.io/js/alertifyjs) |
|||
[![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/alertifyjs/badge?style=rounded)](https://www.jsdelivr.com/package/npm/alertifyjs) |
|||
|
|||
AlertifyJS |
|||
========== |
|||
|
|||
[![Join the chat at https://gitter.im/MohammadYounes/AlertifyJS](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/MohammadYounes/AlertifyJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) |
|||
|
|||
AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications. |
|||
|
|||
> AlertifyJS is an extreme makeover of <a href="http://www.github.com/fabien-d/alertify.js">alertify.js</a> by <a href="http://www.github.com/fabien-d">@fabien-d</a> |
|||
|
|||
|
|||
|
|||
### Install with [NuGet](https://www.nuget.org/packages/AlertifyJS/) |
|||
|
|||
``` |
|||
Install-Package AlertifyJS |
|||
``` |
|||
|
|||
### Install with [NPM](https://www.npmjs.com/package/alertifyjs/) |
|||
|
|||
``` |
|||
npm install alertifyjs --save |
|||
``` |
|||
|
|||
|
|||
Documentation |
|||
========== |
|||
Check out the interactive documentation at http://alertifyjs.com |
|||
|
|||
[![alertifyjs-dialog](https://cloud.githubusercontent.com/assets/4712046/4170670/0d50b04c-3535-11e4-87a7-1ce62dd0d77e.png)](http://alertifyjs.com) |
|||
|
|||
|
|||
Browser support |
|||
========== |
|||
Last two versions. |
|||
|
|||
|
|||
|
|||
Running documentation locally |
|||
========== |
|||
* Clone the repo |
|||
``` |
|||
git clone git@github.com:MohammadYounes/AlertifyJS.git |
|||
``` |
|||
|
|||
* Install dev dependencies |
|||
``` |
|||
npm update; npm install; |
|||
``` |
|||
|
|||
* Build the project |
|||
``` |
|||
grunt |
|||
``` |
|||
|
|||
* Start documentation server |
|||
``` |
|||
docpad run |
|||
``` |
|||
* Open your browser to http://localhost:9778/ |
|||
|
|||
|
|||
Dependencies |
|||
========== |
|||
None. |
|||
|
|||
|
|||
Community Contribution |
|||
========== |
|||
|
|||
* [alertifyjs-rails](https://github.com/mkhairi/alertifyjs-rails) by **[@mkhairi](https://github.com/mkhairi)** |
|||
* [meteor-alertifyjs](https://github.com/ovcharik/meteor-alertifyjs/) by **[@ovcharik](https://github.com/ovcharik)** |
|||
|
|||
Bugs & Questions |
|||
========== |
|||
Please review the guidelines for [contributing](https://github.com/MohammadYounes/AlertifyJS/blob/master/CONTRIBUTING.md). |
|||
>You can fork this [codepen](http://codepen.io/anon/pen/raohK) or this [jsfiddle](http://jsfiddle.net/g2o52zq7/) to get started. |
|||
|
|||
|
|||
------ |
|||
Contact: [Mohammad@alertifyjs.com](mailto:Mohammad@alertifyjs.com) |
@ -0,0 +1,165 @@ |
|||
# Release Notes |
|||
|
|||
* **v1.12.0** [28 Sep. 2019] |
|||
* New API features: |
|||
* `invokeOnCloseOff` option. #218/#219 |
|||
* Global pre/post init hooks. #216 |
|||
* Expose notifier classes, allowing them to be renamed. #217 |
|||
* Add `defaultFocusOff` option to Confirm dialog. #212 |
|||
* Fix locking in tab cycle inside modals. |
|||
|
|||
* **v1.11.4** [17 Jun. 2018] |
|||
* Fix SCRIPT5045: Assignment to read-only properties is not allowed in strict mode (IE11). #210 |
|||
|
|||
* **v1.11.3** [31 May. 2018] |
|||
* Prevent FOUC in case of async styles loading. #205 |
|||
* Ensure `preventBodyShift` restores scrollbars. #206 |
|||
|
|||
* **v1.11.2** [30 Oct. 2018] |
|||
* Prevent triggering duplicate callbacks - #199 |
|||
|
|||
* **v1.11.1** [24 Mar. 2018] |
|||
* Set body `tabindex` only when a dialog is shown. #145 |
|||
* Remove duplicate case statement. #181 |
|||
|
|||
* **v1.11.0** [4 Aug. 2017] |
|||
* Adds `top-center` and `bottom-center` position options for notifier. #13 |
|||
|
|||
* **v1.10.0** [12 Apr. 2017] |
|||
* New `onclosing` event: Gets or sets a function to invoke when the dialog is about to close. #140 |
|||
|
|||
* **v1.9.0** [26 Jan. 2017] |
|||
* New notifier global option `closeButton` to add a close button to notifications, This feature helps users copy the contents of a message. Thanks (@pmusaraj - #134). |
|||
|
|||
* **v1.8.0** [30 Jul. 2016] |
|||
* Change license to GPLv3. |
|||
* New global option `preventBodyShift` to prevent body shifting when showing a modal dialog, You may get a double scrollbar when dialog content overflows the screen. |
|||
* Fixes a bug where some dialog options were uninitialized by the factory function. #108 |
|||
|
|||
* **v1.7.1** [8 Jun. 2016] |
|||
* Reset Prompt Dialog default value on cancellation. #106 |
|||
|
|||
* **v1.7.0** [26 May. 2016] |
|||
* New API feature - Extended set of event callbacks: |
|||
* `onmove`: Gets or sets a function to invoke when the dialog is about to move. |
|||
* `onmoved`: Gets or sets a function to invoke once the dialog has been moved. |
|||
* `onresize`: Gets or sets a function to invoke when the dialog is about to resize. |
|||
* `onresized`: Gets or sets a function to invoke once the dialog has been resized. |
|||
* `onmaximize`: Gets or sets a function to invoke when the dialog is about to maximize. |
|||
* `onmaximized`: Gets or sets a function to invoke once the dialog has been maximized. |
|||
* `onrestore`: Gets or sets a function to invoke when a maximized dialog is about to restore. |
|||
* `onrestored`: Gets or sets a function to invoke once a maximized dialog has been restored. |
|||
|
|||
* **v1.6.1** [20 Jan. 2016] |
|||
* Fixes a bug in removing classes from `body` element. #86 |
|||
|
|||
* **v1.6.0** [23 Nov. 2015] |
|||
* New API feature: `bringToFront` method and `moveBounded` option. |
|||
|
|||
* **v1.5.0** [28 Sep. 2015] |
|||
* New API feature: `destroy` method. |
|||
* Fixes maintaining scroll position in IE. #76 |
|||
|
|||
* **v1.4.1** [12 May. 2015] |
|||
* Fixes Prompt Dialog value handling. #59 |
|||
|
|||
* **v1.4.0** [22 Apr. 2015] |
|||
* Prompt dialog: Added support for changing the HTML type of the input field. |
|||
* Support percent unit in `ResizeTo` method. |
|||
* Maintain document scroll position. |
|||
* Allow reusing dialog contents by not destroying the DOM, plus faster content clearing. |
|||
* Fixes the context for some callbacks. |
|||
|
|||
* **v1.3.0** [14 Mar. 2015] |
|||
* New API feature: `autoReset` option to control whether to reset dialog size/position on window resize or not. |
|||
* Always use a copy of buttons definition. Fixes #32 |
|||
|
|||
* **v1.2.1** [06 Mar. 2015] |
|||
* Add default colors to core CSS, to make it easier to start a theme based on it. |
|||
* Fixes a problem with using AlertifyJS in Ember-CLI. #27 |
|||
|
|||
* **v1.2.0** [17 Feb. 2015] |
|||
* New API feature: `closableByDimmer` option. |
|||
* Published to [NPM](https://www.npmjs.com/package/alertifyjs) **Thanks @dantman** |
|||
* Support installation via `npm install alertifyjs --save`. |
|||
* Support use of `require('alertifyjs')` in loaders such as Browserify. |
|||
|
|||
* **v1.1.0** [24 Jan. 2015] |
|||
* New API event hooks for dialog developers (onshow, onclose, onupdate) |
|||
* Support move for frameless dialogs. |
|||
* Fix Move/Resize mouse events capture when dialog contains an iframe. |
|||
|
|||
* **v1.0.1** [11 Jan. 2015] |
|||
* Re-append notifier div when body content is replaced. Fixes #17 |
|||
|
|||
* **v1.0.0** [10 Jan. 2015] |
|||
* First official release. |
|||
|
|||
* **v0.10.2** [31 Oct. 2014] |
|||
* Add missing notifier styles to Semantic/Bootstrap themes. |
|||
|
|||
* **v0.10.1** [30 Oct. 2014] |
|||
* Fix ESC key handling for button-less dialogs. |
|||
|
|||
* **v0.10.0** [30 Oct. 2014] |
|||
* Ability to use arrow keys to switch between dialog buttons. |
|||
* New API features: |
|||
* Frameless dialog view mode. |
|||
* Start maximized option. |
|||
* Move the dialog to a specific X,Y coordinates: `moveTo`. |
|||
* Resize the dialog to a specific Width,Height : `resizeTo`. |
|||
* Fixes: |
|||
* Fix initial resizable width for IE. |
|||
* Fix resize bug when body contents height is smaller than window size. |
|||
|
|||
* **v0.9.0** [14 Oct. 2014] |
|||
* New API feature: new options to determine focus element. |
|||
|
|||
* **v0.8.0** [11 Oct. 2014] |
|||
* New dialog option: Basic view mode. |
|||
* Support creating button-less dialogs. |
|||
* Fixes tab cycle for Opera. |
|||
* Fixes missing focus outline for FireFox. |
|||
* Fixes prompt dialog 5-paramters constructor. **Thanks @TomTasche** |
|||
|
|||
* **v0.7.0** [27 Sep. 2014] |
|||
* New API features : |
|||
* Close all open dialogs |
|||
* Close all open dialogs except current. |
|||
* Dismiss all open notifications |
|||
* Dismiss all open notifications except current. |
|||
|
|||
* **v0.6.1** [22 Sep. 2014] |
|||
* Fixes Null reference error when including alertify script before body element. |
|||
|
|||
* **v0.6.0** [21 Sep. 2014] |
|||
* Prefix the names of all animations with `ajs-` (Prevents collision with other frameworks) |
|||
* Listen to `animationend` event instead of `transitionend`. |
|||
* Isolate transition fallback timers (per instance). |
|||
|
|||
* **v0.5.0** [20 Sep. 2014] |
|||
* Notifier API now returns notification object. |
|||
* Add `get`/`set` aliases for `.setting` API. |
|||
* New global option (`alertify.defaults.maintainFocus`:`true`), controls whether to maintain active element focus or not. |
|||
|
|||
* **v0.4.0** [07 Sep. 2014] |
|||
* Add touch devices support. |
|||
|
|||
* **v0.3.1** [03 Sep. 2014] |
|||
* Fixes bug where transition could accidentally hide the dialog on show. |
|||
|
|||
* **v0.3.0** [03 Sep. 2014] |
|||
* Fix dialog is invisible in Desktop Safari. |
|||
* Enable binding to Function Keys. |
|||
|
|||
* **v0.2.0** [25 Aug. 2014] |
|||
* disable move when there is an active resize (possible when mouse up is triggered outside browser window). |
|||
* clear movable/resizable on close. |
|||
* docs enhancements. |
|||
|
|||
* **v0.1.0** [12 Aug. 2014] |
|||
* Add custom `onfocus` callback. |
|||
* Fix content padding. |
|||
|
|||
* **v0.0.0** [1 Aug. 2014] |
|||
* Initial commit. |
@ -0,0 +1,56 @@ |
|||
{ |
|||
"name": "alertifyjs", |
|||
"version": "1.12.0", |
|||
"description": "AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.", |
|||
"homepage": "http://alertifyjs.com", |
|||
"keywords": [ |
|||
"alertifyjs", |
|||
"alert", |
|||
"confirm", |
|||
"prompt", |
|||
"dialog", |
|||
"alertify", |
|||
"javascript framework", |
|||
"pretty dialogs" |
|||
], |
|||
"author": "Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)", |
|||
"bugs": { |
|||
"url": "https://github.com/MohammadYounes/AlertifyJS/issues" |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git@github.com:MohammadYounes/AlertifyJS.git" |
|||
}, |
|||
"main": "./build/alertify.js", |
|||
"devDependencies": { |
|||
"grunt": "~0.4.1", |
|||
"grunt-cli": "~0.1", |
|||
"grunt-rtlcss": "1.6.0", |
|||
"autoprefixer" : "x.x.x", |
|||
"grunt-postcss" : "~0.8.0", |
|||
"grunt-contrib-less": "x.x.x", |
|||
"grunt-contrib-cssmin": "x.x.x", |
|||
"grunt-contrib-copy": "x.x.x", |
|||
"grunt-contrib-jshint": "~0.6.4", |
|||
"grunt-contrib-uglify": "~0.9.1", |
|||
"grunt-contrib-clean": "~0.5.0", |
|||
"grunt-contrib-concat": "~0.3.0", |
|||
"grunt-contrib-watch": "~0.5.3", |
|||
"grunt-contrib-connect": "~0.5.0", |
|||
"grunt-contrib-compress": "x.x.x", |
|||
"grunt-banner": "~0.3.1", |
|||
"docpad": "~6.69.0", |
|||
"docpad-plugin-eco": "~2.1.0", |
|||
"docpad-plugin-marked": "~2.2.1", |
|||
"docpad-plugin-partials": "~2.9.1", |
|||
"docpad-plugin-highlightjs": "~2.2.2", |
|||
"docpad-plugin-ghpages": "~2.4.3", |
|||
"docpad-plugin-livereload": "~2.6.0" |
|||
}, |
|||
"licenses": [ |
|||
{ |
|||
"type": "GPL 3", |
|||
"url": "https://opensource.org/licenses/gpl-3.0" |
|||
} |
|||
] |
|||
} |
@ -0,0 +1,93 @@ |
|||
/** |
|||
* Alert dialog definition |
|||
* |
|||
* invoked by: |
|||
* alertify.alert(message); |
|||
* alertify.alert(title, message); |
|||
* alertify.alert(message, onok); |
|||
* alertify.alert(title, message, onok); |
|||
*/ |
|||
alertify.dialog('alert', function () { |
|||
return { |
|||
main: function (_title, _message, _onok) { |
|||
var title, message, onok; |
|||
switch (arguments.length) { |
|||
case 1: |
|||
message = _title; |
|||
break; |
|||
case 2: |
|||
if (typeof _message === 'function') { |
|||
message = _title; |
|||
onok = _message; |
|||
} else { |
|||
title = _title; |
|||
message = _message; |
|||
} |
|||
break; |
|||
case 3: |
|||
title = _title; |
|||
message = _message; |
|||
onok = _onok; |
|||
break; |
|||
} |
|||
this.set('title', title); |
|||
this.set('message', message); |
|||
this.set('onok', onok); |
|||
return this; |
|||
}, |
|||
setup: function () { |
|||
return { |
|||
buttons: [ |
|||
{ |
|||
text: alertify.defaults.glossary.ok, |
|||
key: keys.ESC, |
|||
invokeOnClose: true, |
|||
className: alertify.defaults.theme.ok, |
|||
} |
|||
], |
|||
focus: { |
|||
element: 0, |
|||
select: false |
|||
}, |
|||
options: { |
|||
maximizable: false, |
|||
resizable: false |
|||
} |
|||
}; |
|||
}, |
|||
build: function () { |
|||
// nothing
|
|||
}, |
|||
prepare: function () { |
|||
//nothing
|
|||
}, |
|||
setMessage: function (message) { |
|||
this.setContent(message); |
|||
}, |
|||
settings: { |
|||
message: undefined, |
|||
onok: undefined, |
|||
label: undefined, |
|||
}, |
|||
settingUpdated: function (key, oldValue, newValue) { |
|||
switch (key) { |
|||
case 'message': |
|||
this.setMessage(newValue); |
|||
break; |
|||
case 'label': |
|||
if (this.__internal.buttons[0].element) { |
|||
this.__internal.buttons[0].element.innerHTML = newValue; |
|||
} |
|||
break; |
|||
} |
|||
}, |
|||
callback: function (closeEvent) { |
|||
if (typeof this.get('onok') === 'function') { |
|||
var returnValue = this.get('onok').call(this, closeEvent); |
|||
if (typeof returnValue !== 'undefined') { |
|||
closeEvent.cancel = !returnValue; |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
}); |
@ -0,0 +1,264 @@ |
|||
/** |
|||
* Alertify public API |
|||
* This contains everything that is exposed through the alertify object. |
|||
* |
|||
* @return {Object} |
|||
*/ |
|||
function Alertify() { |
|||
|
|||
// holds a references of created dialogs
|
|||
var dialogs = {}; |
|||
|
|||
/** |
|||
* Extends a given prototype by merging properties from base into sub. |
|||
* |
|||
* @sub {Object} sub The prototype being overwritten. |
|||
* @base {Object} base The prototype being written. |
|||
* |
|||
* @return {Object} The extended prototype. |
|||
*/ |
|||
function extend(sub, base) { |
|||
// copy dialog pototype over definition.
|
|||
for (var prop in base) { |
|||
if (base.hasOwnProperty(prop)) { |
|||
sub[prop] = base[prop]; |
|||
} |
|||
} |
|||
return sub; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Helper: returns a dialog instance from saved dialogs. |
|||
* and initializes the dialog if its not already initialized. |
|||
* |
|||
* @name {String} name The dialog name. |
|||
* |
|||
* @return {Object} The dialog instance. |
|||
*/ |
|||
function get_dialog(name) { |
|||
var dialog = dialogs[name].dialog; |
|||
//initialize the dialog if its not already initialized.
|
|||
if (dialog && typeof dialog.__init === 'function') { |
|||
dialog.__init(dialog); |
|||
} |
|||
return dialog; |
|||
} |
|||
|
|||
/** |
|||
* Helper: registers a new dialog definition. |
|||
* |
|||
* @name {String} name The dialog name. |
|||
* @Factory {Function} Factory a function resposible for creating dialog prototype. |
|||
* @transient {Boolean} transient True to create a new dialog instance each time the dialog is invoked, false otherwise. |
|||
* @base {String} base the name of another dialog to inherit from. |
|||
* |
|||
* @return {Object} The dialog definition. |
|||
*/ |
|||
function register(name, Factory, transient, base) { |
|||
var definition = { |
|||
dialog: null, |
|||
factory: Factory |
|||
}; |
|||
|
|||
//if this is based on an existing dialog, create a new definition
|
|||
//by applying the new protoype over the existing one.
|
|||
if (base !== undefined) { |
|||
definition.factory = function () { |
|||
return extend(new dialogs[base].factory(), new Factory()); |
|||
}; |
|||
} |
|||
|
|||
if (!transient) { |
|||
//create a new definition based on dialog
|
|||
definition.dialog = extend(new definition.factory(), dialog); |
|||
} |
|||
return dialogs[name] = definition; |
|||
} |
|||
|
|||
return { |
|||
/** |
|||
* Alertify defaults |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
defaults: defaults, |
|||
/** |
|||
* Dialogs factory |
|||
* |
|||
* @param {string} Dialog name. |
|||
* @param {Function} A Dialog factory function. |
|||
* @param {Boolean} Indicates whether to create a singleton or transient dialog. |
|||
* @param {String} The name of the base type to inherit from. |
|||
*/ |
|||
dialog: function (name, Factory, transient, base) { |
|||
|
|||
// get request, create a new instance and return it.
|
|||
if (typeof Factory !== 'function') { |
|||
return get_dialog(name); |
|||
} |
|||
|
|||
if (this.hasOwnProperty(name)) { |
|||
throw new Error('alertify.dialog: name already exists'); |
|||
} |
|||
|
|||
// register the dialog
|
|||
var definition = register(name, Factory, transient, base); |
|||
|
|||
if (transient) { |
|||
|
|||
// make it public
|
|||
this[name] = function () { |
|||
//if passed with no params, consider it a get request
|
|||
if (arguments.length === 0) { |
|||
return definition.dialog; |
|||
} else { |
|||
var instance = extend(new definition.factory(), dialog); |
|||
//ensure init
|
|||
if (instance && typeof instance.__init === 'function') { |
|||
instance.__init(instance); |
|||
} |
|||
instance['main'].apply(instance, arguments); |
|||
return instance['show'].apply(instance); |
|||
} |
|||
}; |
|||
} else { |
|||
// make it public
|
|||
this[name] = function () { |
|||
//ensure init
|
|||
if (definition.dialog && typeof definition.dialog.__init === 'function') { |
|||
definition.dialog.__init(definition.dialog); |
|||
} |
|||
//if passed with no params, consider it a get request
|
|||
if (arguments.length === 0) { |
|||
return definition.dialog; |
|||
} else { |
|||
var dialog = definition.dialog; |
|||
dialog['main'].apply(definition.dialog, arguments); |
|||
return dialog['show'].apply(definition.dialog); |
|||
} |
|||
}; |
|||
} |
|||
}, |
|||
/** |
|||
* Close all open dialogs. |
|||
* |
|||
* @param {Object} excpet [optional] The dialog object to exclude from closing. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
closeAll: function (except) { |
|||
var clone = openDialogs.slice(0); |
|||
for (var x = 0; x < clone.length; x += 1) { |
|||
var instance = clone[x]; |
|||
if (except === undefined || except !== instance) { |
|||
instance.close(); |
|||
} |
|||
} |
|||
}, |
|||
/** |
|||
* Gets or Sets dialog settings/options. if the dialog is transient, this call does nothing. |
|||
* |
|||
* @param {string} name The dialog name. |
|||
* @param {String|Object} key A string specifying a propery name or a collection of key/value pairs. |
|||
* @param {Variant} value Optional, the value associated with the key (in case it was a string). |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
setting: function (name, key, value) { |
|||
|
|||
if (name === 'notifier') { |
|||
return notifier.setting(key, value); |
|||
} |
|||
|
|||
var dialog = get_dialog(name); |
|||
if (dialog) { |
|||
return dialog.setting(key, value); |
|||
} |
|||
}, |
|||
/** |
|||
* [Alias] Sets dialog settings/options |
|||
*/ |
|||
set: function(name,key,value){ |
|||
return this.setting(name, key,value); |
|||
}, |
|||
/** |
|||
* [Alias] Gets dialog settings/options |
|||
*/ |
|||
get: function(name, key){ |
|||
return this.setting(name, key); |
|||
}, |
|||
/** |
|||
* Creates a new notification message. |
|||
* If a type is passed, a class name "ajs-{type}" will be added. |
|||
* This allows for custom look and feel for various types of notifications. |
|||
* |
|||
* @param {String | DOMElement} [message=undefined] Message text |
|||
* @param {String} [type=''] Type of log message |
|||
* @param {String} [wait=''] Time (in seconds) to wait before auto-close |
|||
* @param {Function} [callback=undefined] A callback function to be invoked when the log is closed. |
|||
* |
|||
* @return {Object} Notification object. |
|||
*/ |
|||
notify: function (message, type, wait, callback) { |
|||
return notifier.create(type, callback).push(message, wait); |
|||
}, |
|||
/** |
|||
* Creates a new notification message. |
|||
* |
|||
* @param {String} [message=undefined] Message text |
|||
* @param {String} [wait=''] Time (in seconds) to wait before auto-close |
|||
* @param {Function} [callback=undefined] A callback function to be invoked when the log is closed. |
|||
* |
|||
* @return {Object} Notification object. |
|||
*/ |
|||
message: function (message, wait, callback) { |
|||
return notifier.create(null, callback).push(message, wait); |
|||
}, |
|||
/** |
|||
* Creates a new notification message of type 'success'. |
|||
* |
|||
* @param {String} [message=undefined] Message text |
|||
* @param {String} [wait=''] Time (in seconds) to wait before auto-close |
|||
* @param {Function} [callback=undefined] A callback function to be invoked when the log is closed. |
|||
* |
|||
* @return {Object} Notification object. |
|||
*/ |
|||
success: function (message, wait, callback) { |
|||
return notifier.create('success', callback).push(message, wait); |
|||
}, |
|||
/** |
|||
* Creates a new notification message of type 'error'. |
|||
* |
|||
* @param {String} [message=undefined] Message text |
|||
* @param {String} [wait=''] Time (in seconds) to wait before auto-close |
|||
* @param {Function} [callback=undefined] A callback function to be invoked when the log is closed. |
|||
* |
|||
* @return {Object} Notification object. |
|||
*/ |
|||
error: function (message, wait, callback) { |
|||
return notifier.create('error', callback).push(message, wait); |
|||
}, |
|||
/** |
|||
* Creates a new notification message of type 'warning'. |
|||
* |
|||
* @param {String} [message=undefined] Message text |
|||
* @param {String} [wait=''] Time (in seconds) to wait before auto-close |
|||
* @param {Function} [callback=undefined] A callback function to be invoked when the log is closed. |
|||
* |
|||
* @return {Object} Notification object. |
|||
*/ |
|||
warning: function (message, wait, callback) { |
|||
return notifier.create('warning', callback).push(message, wait); |
|||
}, |
|||
/** |
|||
* Dismisses all open notifications |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
dismissAll: function () { |
|||
notifier.dismissAll(); |
|||
} |
|||
}; |
|||
} |
|||
var alertify = new Alertify(); |
@ -0,0 +1,186 @@ |
|||
/** |
|||
* Confirm dialog object |
|||
* |
|||
* alertify.confirm(message); |
|||
* alertify.confirm(message, onok); |
|||
* alertify.confirm(message, onok, oncancel); |
|||
* alertify.confirm(title, message, onok, oncancel); |
|||
*/ |
|||
alertify.dialog('confirm', function () { |
|||
|
|||
var autoConfirm = { |
|||
timer: null, |
|||
index: null, |
|||
text: null, |
|||
duration: null, |
|||
task: function (event, self) { |
|||
if (self.isOpen()) { |
|||
self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text + ' (‏' + autoConfirm.duration + '‏) '; |
|||
autoConfirm.duration -= 1; |
|||
if (autoConfirm.duration === -1) { |
|||
clearAutoConfirm(self); |
|||
var button = self.__internal.buttons[autoConfirm.index]; |
|||
var closeEvent = createCloseEvent(autoConfirm.index, button); |
|||
|
|||
if (typeof self.callback === 'function') { |
|||
self.callback.apply(self, [closeEvent]); |
|||
} |
|||
//close the dialog.
|
|||
if (closeEvent.close !== false) { |
|||
self.close(); |
|||
} |
|||
} |
|||
} else { |
|||
clearAutoConfirm(self); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
function clearAutoConfirm(self) { |
|||
if (autoConfirm.timer !== null) { |
|||
clearInterval(autoConfirm.timer); |
|||
autoConfirm.timer = null; |
|||
self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text; |
|||
} |
|||
} |
|||
|
|||
function startAutoConfirm(self, index, duration) { |
|||
clearAutoConfirm(self); |
|||
autoConfirm.duration = duration; |
|||
autoConfirm.index = index; |
|||
autoConfirm.text = self.__internal.buttons[index].element.innerHTML; |
|||
autoConfirm.timer = setInterval(delegate(self, autoConfirm.task), 1000); |
|||
autoConfirm.task(null, self); |
|||
} |
|||
|
|||
|
|||
return { |
|||
main: function (_title, _message, _onok, _oncancel) { |
|||
var title, message, onok, oncancel; |
|||
switch (arguments.length) { |
|||
case 1: |
|||
message = _title; |
|||
break; |
|||
case 2: |
|||
message = _title; |
|||
onok = _message; |
|||
break; |
|||
case 3: |
|||
message = _title; |
|||
onok = _message; |
|||
oncancel = _onok; |
|||
break; |
|||
case 4: |
|||
title = _title; |
|||
message = _message; |
|||
onok = _onok; |
|||
oncancel = _oncancel; |
|||
break; |
|||
} |
|||
this.set('title', title); |
|||
this.set('message', message); |
|||
this.set('onok', onok); |
|||
this.set('oncancel', oncancel); |
|||
return this; |
|||
}, |
|||
setup: function () { |
|||
return { |
|||
buttons: [ |
|||
{ |
|||
text: alertify.defaults.glossary.ok, |
|||
key: keys.ENTER, |
|||
className: alertify.defaults.theme.ok, |
|||
}, |
|||
{ |
|||
text: alertify.defaults.glossary.cancel, |
|||
key: keys.ESC, |
|||
invokeOnClose: true, |
|||
className: alertify.defaults.theme.cancel, |
|||
} |
|||
], |
|||
focus: { |
|||
element: 0, |
|||
select: false |
|||
}, |
|||
options: { |
|||
maximizable: false, |
|||
resizable: false |
|||
} |
|||
}; |
|||
}, |
|||
build: function () { |
|||
//nothing
|
|||
}, |
|||
prepare: function () { |
|||
//nothing
|
|||
}, |
|||
setMessage: function (message) { |
|||
this.setContent(message); |
|||
}, |
|||
settings: { |
|||
message: null, |
|||
labels: null, |
|||
onok: null, |
|||
oncancel: null, |
|||
defaultFocus: null, |
|||
reverseButtons: null, |
|||
}, |
|||
settingUpdated: function (key, oldValue, newValue) { |
|||
switch (key) { |
|||
case 'message': |
|||
this.setMessage(newValue); |
|||
break; |
|||
case 'labels': |
|||
if ('ok' in newValue && this.__internal.buttons[0].element) { |
|||
this.__internal.buttons[0].text = newValue.ok; |
|||
this.__internal.buttons[0].element.innerHTML = newValue.ok; |
|||
} |
|||
if ('cancel' in newValue && this.__internal.buttons[1].element) { |
|||
this.__internal.buttons[1].text = newValue.cancel; |
|||
this.__internal.buttons[1].element.innerHTML = newValue.cancel; |
|||
} |
|||
break; |
|||
case 'reverseButtons': |
|||
if (newValue === true) { |
|||
this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element); |
|||
} else { |
|||
this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element); |
|||
} |
|||
break; |
|||
case 'defaultFocus': |
|||
this.__internal.focus.element = newValue === 'ok' ? 0 : 1; |
|||
break; |
|||
} |
|||
}, |
|||
callback: function (closeEvent) { |
|||
clearAutoConfirm(this); |
|||
var returnValue; |
|||
switch (closeEvent.index) { |
|||
case 0: |
|||
if (typeof this.get('onok') === 'function') { |
|||
returnValue = this.get('onok').call(this, closeEvent); |
|||
if (typeof returnValue !== 'undefined') { |
|||
closeEvent.cancel = !returnValue; |
|||
} |
|||
} |
|||
break; |
|||
case 1: |
|||
if (typeof this.get('oncancel') === 'function') { |
|||
returnValue = this.get('oncancel').call(this, closeEvent); |
|||
if (typeof returnValue !== 'undefined') { |
|||
closeEvent.cancel = !returnValue; |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
}, |
|||
autoOk: function (duration) { |
|||
startAutoConfirm(this, 0, duration); |
|||
return this; |
|||
}, |
|||
autoCancel: function (duration) { |
|||
startAutoConfirm(this, 1, duration); |
|||
return this; |
|||
} |
|||
}; |
|||
}); |
@ -0,0 +1,109 @@ |
|||
// stores last call timestamp to prevent triggering the callback twice.
|
|||
var callbackTS = 0; |
|||
// flag to cancel keyup event if already handled by click event (pressing Enter on a focusted button).
|
|||
var cancelKeyup = false; |
|||
/** |
|||
* Helper: triggers a button callback |
|||
* |
|||
* @param {Object} The dilog instance. |
|||
* @param {Function} Callback to check which button triggered the event. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function triggerCallback(instance, check) { |
|||
if(Date.now() - callbackTS > 200 && (callbackTS = Date.now())){ |
|||
for (var idx = 0; idx < instance.__internal.buttons.length; idx += 1) { |
|||
var button = instance.__internal.buttons[idx]; |
|||
if (!button.element.disabled && check(button)) { |
|||
var closeEvent = createCloseEvent(idx, button); |
|||
if (typeof instance.callback === 'function') { |
|||
instance.callback.apply(instance, [closeEvent]); |
|||
} |
|||
//close the dialog only if not canceled.
|
|||
if (closeEvent.cancel === false) { |
|||
instance.close(); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Clicks event handler, attached to the dialog footer. |
|||
* |
|||
* @param {Event} DOM event object. |
|||
* @param {Object} The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function buttonsClickHandler(event, instance) { |
|||
var target = event.srcElement || event.target; |
|||
triggerCallback(instance, function (button) { |
|||
// if this button caused the click, cancel keyup event
|
|||
return button.element === target && (cancelKeyup = true); |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Keyup event handler, attached to the document.body |
|||
* |
|||
* @param {Event} DOM event object. |
|||
* @param {Object} The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function keyupHandler(event) { |
|||
//hitting enter while button has focus will trigger keyup too.
|
|||
//ignore if handled by clickHandler
|
|||
if (cancelKeyup) { |
|||
cancelKeyup = false; |
|||
return; |
|||
} |
|||
var instance = openDialogs[openDialogs.length - 1]; |
|||
var keyCode = event.keyCode; |
|||
if (instance.__internal.buttons.length === 0 && keyCode === keys.ESC && instance.get('closable') === true) { |
|||
triggerClose(instance); |
|||
return false; |
|||
}else if (usedKeys.indexOf(keyCode) > -1) { |
|||
triggerCallback(instance, function (button) { |
|||
return button.key === keyCode; |
|||
}); |
|||
return false; |
|||
} |
|||
} |
|||
/** |
|||
* Keydown event handler, attached to the document.body |
|||
* |
|||
* @param {Event} DOM event object. |
|||
* @param {Object} The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function keydownHandler(event) { |
|||
var instance = openDialogs[openDialogs.length - 1]; |
|||
var keyCode = event.keyCode; |
|||
if (keyCode === keys.LEFT || keyCode === keys.RIGHT) { |
|||
var buttons = instance.__internal.buttons; |
|||
for (var x = 0; x < buttons.length; x += 1) { |
|||
if (document.activeElement === buttons[x].element) { |
|||
switch (keyCode) { |
|||
case keys.LEFT: |
|||
buttons[(x || buttons.length) - 1].element.focus(); |
|||
return; |
|||
case keys.RIGHT: |
|||
buttons[(x + 1) % buttons.length].element.focus(); |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
}else if (keyCode < keys.F12 + 1 && keyCode > keys.F1 - 1 && usedKeys.indexOf(keyCode) > -1) { |
|||
event.preventDefault(); |
|||
event.stopPropagation(); |
|||
triggerCallback(instance, function (button) { |
|||
return button.key === keyCode; |
|||
}); |
|||
return false; |
|||
} |
|||
} |
|||
|
@ -0,0 +1,274 @@ |
|||
|
|||
/** |
|||
* Triggers a close event. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function triggerClose(instance) { |
|||
var found; |
|||
triggerCallback(instance, function (button) { |
|||
return found = instance.get('invokeOnCloseOff') !== true && (button.invokeOnClose === true); |
|||
}); |
|||
//none of the buttons registered as onclose callback
|
|||
//close the dialog
|
|||
if (!found && instance.isOpen()) { |
|||
instance.close(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Dialogs commands event handler, attached to the dialog commands element. |
|||
* |
|||
* @param {Event} event DOM event object. |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function commandsClickHandler(event, instance) { |
|||
var target = event.srcElement || event.target; |
|||
switch (target) { |
|||
case instance.elements.commands.pin: |
|||
if (!instance.isPinned()) { |
|||
pin(instance); |
|||
} else { |
|||
unpin(instance); |
|||
} |
|||
break; |
|||
case instance.elements.commands.maximize: |
|||
if (!instance.isMaximized()) { |
|||
maximize(instance); |
|||
} else { |
|||
restore(instance); |
|||
} |
|||
break; |
|||
case instance.elements.commands.close: |
|||
triggerClose(instance); |
|||
break; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* Helper: pins the modeless dialog. |
|||
* |
|||
* @param {Object} instance The dialog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function pin(instance) { |
|||
//pin the dialog
|
|||
instance.set('pinned', true); |
|||
} |
|||
|
|||
/** |
|||
* Helper: unpins the modeless dialog. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function unpin(instance) { |
|||
//unpin the dialog
|
|||
instance.set('pinned', false); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Helper: enlarges the dialog to fill the entire screen. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function maximize(instance) { |
|||
// allow custom `onmaximize` method
|
|||
dispatchEvent('onmaximize', instance); |
|||
//maximize the dialog
|
|||
addClass(instance.elements.root, classes.maximized); |
|||
if (instance.isOpen()) { |
|||
ensureNoOverflow(); |
|||
} |
|||
// allow custom `onmaximized` method
|
|||
dispatchEvent('onmaximized', instance); |
|||
} |
|||
|
|||
/** |
|||
* Helper: returns the dialog to its former size. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function restore(instance) { |
|||
// allow custom `onrestore` method
|
|||
dispatchEvent('onrestore', instance); |
|||
//maximize the dialog
|
|||
removeClass(instance.elements.root, classes.maximized); |
|||
if (instance.isOpen()) { |
|||
ensureNoOverflow(); |
|||
} |
|||
// allow custom `onrestored` method
|
|||
dispatchEvent('onrestored', instance); |
|||
} |
|||
|
|||
/** |
|||
* Show or hide the maximize box. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {Boolean} on True to add the behavior, removes it otherwise. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updatePinnable(instance) { |
|||
if (instance.get('pinnable')) { |
|||
// add class
|
|||
addClass(instance.elements.root, classes.pinnable); |
|||
} else { |
|||
// remove class
|
|||
removeClass(instance.elements.root, classes.pinnable); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Helper: Fixes the absolutly positioned modal div position. |
|||
* |
|||
* @param {Object} instance The dialog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function addAbsPositionFix(instance) { |
|||
var scrollLeft = getScrollLeft(); |
|||
instance.elements.modal.style.marginTop = getScrollTop() + 'px'; |
|||
instance.elements.modal.style.marginLeft = scrollLeft + 'px'; |
|||
instance.elements.modal.style.marginRight = (-scrollLeft) + 'px'; |
|||
} |
|||
|
|||
/** |
|||
* Helper: Removes the absolutly positioned modal div position fix. |
|||
* |
|||
* @param {Object} instance The dialog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function removeAbsPositionFix(instance) { |
|||
var marginTop = parseInt(instance.elements.modal.style.marginTop, 10); |
|||
var marginLeft = parseInt(instance.elements.modal.style.marginLeft, 10); |
|||
instance.elements.modal.style.marginTop = ''; |
|||
instance.elements.modal.style.marginLeft = ''; |
|||
instance.elements.modal.style.marginRight = ''; |
|||
|
|||
if (instance.isOpen()) { |
|||
var top = 0, |
|||
left = 0 |
|||
; |
|||
if (instance.elements.dialog.style.top !== '') { |
|||
top = parseInt(instance.elements.dialog.style.top, 10); |
|||
} |
|||
instance.elements.dialog.style.top = (top + (marginTop - getScrollTop())) + 'px'; |
|||
|
|||
if (instance.elements.dialog.style.left !== '') { |
|||
left = parseInt(instance.elements.dialog.style.left, 10); |
|||
} |
|||
instance.elements.dialog.style.left = (left + (marginLeft - getScrollLeft())) + 'px'; |
|||
} |
|||
} |
|||
/** |
|||
* Helper: Adds/Removes the absolutly positioned modal div position fix based on its pinned setting. |
|||
* |
|||
* @param {Object} instance The dialog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updateAbsPositionFix(instance) { |
|||
// if modeless and unpinned add fix
|
|||
if (!instance.get('modal') && !instance.get('pinned')) { |
|||
addAbsPositionFix(instance); |
|||
} else { |
|||
removeAbsPositionFix(instance); |
|||
} |
|||
} |
|||
/** |
|||
* Toggles the dialog position lock | modeless only. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {Boolean} on True to make it modal, false otherwise. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updatePinned(instance) { |
|||
if (instance.get('pinned')) { |
|||
removeClass(instance.elements.root, classes.unpinned); |
|||
if (instance.isOpen()) { |
|||
removeAbsPositionFix(instance); |
|||
} |
|||
} else { |
|||
addClass(instance.elements.root, classes.unpinned); |
|||
if (instance.isOpen() && !instance.isModal()) { |
|||
addAbsPositionFix(instance); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Show or hide the maximize box. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {Boolean} on True to add the behavior, removes it otherwise. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updateMaximizable(instance) { |
|||
if (instance.get('maximizable')) { |
|||
// add class
|
|||
addClass(instance.elements.root, classes.maximizable); |
|||
} else { |
|||
// remove class
|
|||
removeClass(instance.elements.root, classes.maximizable); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Show or hide the close box. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {Boolean} on True to add the behavior, removes it otherwise. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updateClosable(instance) { |
|||
if (instance.get('closable')) { |
|||
// add class
|
|||
addClass(instance.elements.root, classes.closable); |
|||
bindClosableEvents(instance); |
|||
} else { |
|||
// remove class
|
|||
removeClass(instance.elements.root, classes.closable); |
|||
unbindClosableEvents(instance); |
|||
} |
|||
} |
|||
|
|||
|
|||
var cancelClick = false,// flag to cancel click event if already handled by end resize event (the mousedown, mousemove, mouseup sequence fires a click event.).
|
|||
modalClickHandlerTS=0 // stores last click timestamp to prevent executing the handler twice on double click.
|
|||
; |
|||
|
|||
/** |
|||
* Helper: closes the modal dialog when clicking the modal |
|||
* |
|||
* @param {Event} event DOM event object. |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function modalClickHandler(event, instance) { |
|||
if(event.timeStamp - modalClickHandlerTS > 200 && (modalClickHandlerTS = event.timeStamp) && !cancelClick){ |
|||
var target = event.srcElement || event.target; |
|||
if (instance.get('closableByDimmer') === true && target === instance.elements.modal) { |
|||
triggerClose(instance); |
|||
} |
|||
cancelClick = false; |
|||
return false; |
|||
} |
|||
} |
@ -0,0 +1,405 @@ |
|||
// dialog API
|
|||
return { |
|||
__init:initialize, |
|||
/** |
|||
* Check if dialog is currently open |
|||
* |
|||
* @return {Boolean} |
|||
*/ |
|||
isOpen: function () { |
|||
return this.__internal.isOpen; |
|||
}, |
|||
isModal: function (){ |
|||
return this.elements.root.className.indexOf(classes.modeless) < 0; |
|||
}, |
|||
isMaximized:function(){ |
|||
return this.elements.root.className.indexOf(classes.maximized) > -1; |
|||
}, |
|||
isPinned:function(){ |
|||
return this.elements.root.className.indexOf(classes.unpinned) < 0; |
|||
}, |
|||
maximize:function(){ |
|||
if(!this.isMaximized()){ |
|||
maximize(this); |
|||
} |
|||
return this; |
|||
}, |
|||
restore:function(){ |
|||
if(this.isMaximized()){ |
|||
restore(this); |
|||
} |
|||
return this; |
|||
}, |
|||
pin:function(){ |
|||
if(!this.isPinned()){ |
|||
pin(this); |
|||
} |
|||
return this; |
|||
}, |
|||
unpin:function(){ |
|||
if(this.isPinned()){ |
|||
unpin(this); |
|||
} |
|||
return this; |
|||
}, |
|||
bringToFront:function(){ |
|||
bringToFront(null, this); |
|||
return this; |
|||
}, |
|||
/** |
|||
* Move the dialog to a specific x/y coordinates |
|||
* |
|||
* @param {Number} x The new dialog x coordinate in pixels. |
|||
* @param {Number} y The new dialog y coordinate in pixels. |
|||
* |
|||
* @return {Object} The dialog instance. |
|||
*/ |
|||
moveTo:function(x,y){ |
|||
if(!isNaN(x) && !isNaN(y)){ |
|||
// allow custom `onmove` method
|
|||
dispatchEvent('onmove', this); |
|||
|
|||
var element = this.elements.dialog, |
|||
current = element, |
|||
offsetLeft = 0, |
|||
offsetTop = 0; |
|||
|
|||
//subtract existing left,top
|
|||
if (element.style.left) { |
|||
offsetLeft -= parseInt(element.style.left, 10); |
|||
} |
|||
if (element.style.top) { |
|||
offsetTop -= parseInt(element.style.top, 10); |
|||
} |
|||
//calc offset
|
|||
do { |
|||
offsetLeft += current.offsetLeft; |
|||
offsetTop += current.offsetTop; |
|||
} while (current = current.offsetParent); |
|||
|
|||
//calc left, top
|
|||
var left = (x - offsetLeft); |
|||
var top = (y - offsetTop); |
|||
|
|||
//// rtl handling
|
|||
if (isRightToLeft()) { |
|||
left *= -1; |
|||
} |
|||
|
|||
element.style.left = left + 'px'; |
|||
element.style.top = top + 'px'; |
|||
|
|||
// allow custom `onmoved` method
|
|||
dispatchEvent('onmoved', this); |
|||
} |
|||
return this; |
|||
}, |
|||
/** |
|||
* Resize the dialog to a specific width/height (the dialog must be 'resizable'). |
|||
* The dialog can be resized to: |
|||
* A minimum width equal to the initial display width |
|||
* A minimum height equal to the sum of header/footer heights. |
|||
* |
|||
* |
|||
* @param {Number or String} width The new dialog width in pixels or in percent. |
|||
* @param {Number or String} height The new dialog height in pixels or in percent. |
|||
* |
|||
* @return {Object} The dialog instance. |
|||
*/ |
|||
resizeTo:function(width,height){ |
|||
var w = parseFloat(width), |
|||
h = parseFloat(height), |
|||
regex = /(\d*\.\d+|\d+)%/ |
|||
; |
|||
|
|||
if(!isNaN(w) && !isNaN(h) && this.get('resizable') === true){ |
|||
|
|||
// allow custom `onresize` method
|
|||
dispatchEvent('onresize', this); |
|||
|
|||
if(('' + width).match(regex)){ |
|||
w = w / 100 * document.documentElement.clientWidth ; |
|||
} |
|||
|
|||
if(('' + height).match(regex)){ |
|||
h = h / 100 * document.documentElement.clientHeight; |
|||
} |
|||
|
|||
var element = this.elements.dialog; |
|||
if (element.style.maxWidth !== 'none') { |
|||
element.style.minWidth = (minWidth = element.offsetWidth) + 'px'; |
|||
} |
|||
element.style.maxWidth = 'none'; |
|||
element.style.minHeight = this.elements.header.offsetHeight + this.elements.footer.offsetHeight + 'px'; |
|||
element.style.width = w + 'px'; |
|||
element.style.height = h + 'px'; |
|||
|
|||
// allow custom `onresized` method
|
|||
dispatchEvent('onresized', this); |
|||
} |
|||
return this; |
|||
}, |
|||
/** |
|||
* Gets or Sets dialog settings/options |
|||
* |
|||
* @param {String|Object} key A string specifying a propery name or a collection of key/value pairs. |
|||
* @param {Object} value Optional, the value associated with the key (in case it was a string). |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
setting : function (key, value) { |
|||
var self = this; |
|||
var result = update(this, this.__internal.options, function(k,o,n){ optionUpdated(self,k,o,n); }, key, value); |
|||
if(result.op === 'get'){ |
|||
if(result.found){ |
|||
return result.value; |
|||
}else if(typeof this.settings !== 'undefined'){ |
|||
return update(this, this.settings, this.settingUpdated || function(){}, key, value).value; |
|||
}else{ |
|||
return undefined; |
|||
} |
|||
}else if(result.op === 'set'){ |
|||
if(result.items.length > 0){ |
|||
var callback = this.settingUpdated || function(){}; |
|||
for(var x=0;x<result.items.length;x+=1){ |
|||
var item = result.items[x]; |
|||
if(!item.found && typeof this.settings !== 'undefined'){ |
|||
update(this, this.settings, callback, item.key, item.value); |
|||
} |
|||
} |
|||
} |
|||
return this; |
|||
} |
|||
}, |
|||
/** |
|||
* [Alias] Sets dialog settings/options |
|||
*/ |
|||
set:function(key, value){ |
|||
this.setting(key,value); |
|||
return this; |
|||
}, |
|||
/** |
|||
* [Alias] Gets dialog settings/options |
|||
*/ |
|||
get:function(key){ |
|||
return this.setting(key); |
|||
}, |
|||
/** |
|||
* Sets dialog header |
|||
* @content {string or element} |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
setHeader:function(content){ |
|||
if(typeof content === 'string'){ |
|||
clearContents(this.elements.header); |
|||
this.elements.header.innerHTML = content; |
|||
}else if (content instanceof window.HTMLElement && this.elements.header.firstChild !== content){ |
|||
clearContents(this.elements.header); |
|||
this.elements.header.appendChild(content); |
|||
} |
|||
return this; |
|||
}, |
|||
/** |
|||
* Sets dialog contents |
|||
* @content {string or element} |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
setContent:function(content){ |
|||
if(typeof content === 'string'){ |
|||
clearContents(this.elements.content); |
|||
this.elements.content.innerHTML = content; |
|||
}else if (content instanceof window.HTMLElement && this.elements.content.firstChild !== content){ |
|||
clearContents(this.elements.content); |
|||
this.elements.content.appendChild(content); |
|||
} |
|||
return this; |
|||
}, |
|||
/** |
|||
* Show the dialog as modal |
|||
* |
|||
* @return {Object} the dialog instance. |
|||
*/ |
|||
showModal: function(className){ |
|||
return this.show(true, className); |
|||
}, |
|||
/** |
|||
* Show the dialog |
|||
* |
|||
* @return {Object} the dialog instance. |
|||
*/ |
|||
show: function (modal, className) { |
|||
|
|||
// ensure initialization
|
|||
initialize(this); |
|||
|
|||
if ( !this.__internal.isOpen ) { |
|||
|
|||
// add to open dialogs
|
|||
this.__internal.isOpen = true; |
|||
openDialogs.push(this); |
|||
|
|||
// save last focused element
|
|||
if(alertify.defaults.maintainFocus){ |
|||
this.__internal.activeElement = document.activeElement; |
|||
} |
|||
|
|||
// set tabindex attribute on body element this allows script to give it focusable
|
|||
if(!document.body.hasAttribute('tabindex')) { |
|||
document.body.setAttribute( 'tabindex', tabindex = '0'); |
|||
} |
|||
|
|||
//allow custom dom manipulation updates before showing the dialog.
|
|||
if(typeof this.prepare === 'function'){ |
|||
this.prepare(); |
|||
} |
|||
|
|||
bindEvents(this); |
|||
|
|||
if(modal !== undefined){ |
|||
this.set('modal', modal); |
|||
} |
|||
|
|||
//save scroll to prevent document jump
|
|||
saveScrollPosition(); |
|||
|
|||
ensureNoOverflow(); |
|||
|
|||
// allow custom dialog class on show
|
|||
if(typeof className === 'string' && className !== ''){ |
|||
this.__internal.className = className; |
|||
addClass(this.elements.root, className); |
|||
} |
|||
|
|||
// maximize if start maximized
|
|||
if ( this.get('startMaximized')) { |
|||
this.maximize(); |
|||
}else if(this.isMaximized()){ |
|||
restore(this); |
|||
} |
|||
|
|||
updateAbsPositionFix(this); |
|||
this.elements.root.removeAttribute('style'); |
|||
removeClass(this.elements.root, classes.animationOut); |
|||
addClass(this.elements.root, classes.animationIn); |
|||
|
|||
// set 1s fallback in case transition event doesn't fire
|
|||
clearTimeout( this.__internal.timerIn); |
|||
this.__internal.timerIn = setTimeout( this.__internal.transitionInHandler, transition.supported ? 1000 : 100 ); |
|||
|
|||
if(isSafari){ |
|||
// force desktop safari reflow
|
|||
var root = this.elements.root; |
|||
root.style.display = 'none'; |
|||
setTimeout(function(){root.style.display = 'block';}, 0); |
|||
} |
|||
|
|||
//reflow
|
|||
reflow = this.elements.root.offsetWidth; |
|||
|
|||
// show dialog
|
|||
removeClass(this.elements.root, classes.hidden); |
|||
|
|||
// internal on show event
|
|||
if(typeof this.hooks.onshow === 'function'){ |
|||
this.hooks.onshow.call(this); |
|||
} |
|||
|
|||
// allow custom `onshow` method
|
|||
dispatchEvent('onshow', this); |
|||
|
|||
}else{ |
|||
// reset move updates
|
|||
resetMove(this); |
|||
// reset resize updates
|
|||
resetResize(this); |
|||
// shake the dialog to indicate its already open
|
|||
addClass(this.elements.dialog, classes.shake); |
|||
var self = this; |
|||
setTimeout(function(){ |
|||
removeClass(self.elements.dialog, classes.shake); |
|||
},200); |
|||
} |
|||
return this; |
|||
}, |
|||
/** |
|||
* Close the dialog |
|||
* |
|||
* @return {Object} The dialog instance |
|||
*/ |
|||
close: function () { |
|||
if (this.__internal.isOpen ) { |
|||
// custom `onclosing` event
|
|||
if(dispatchEvent('onclosing', this) !== false){ |
|||
|
|||
unbindEvents(this); |
|||
|
|||
removeClass(this.elements.root, classes.animationIn); |
|||
addClass(this.elements.root, classes.animationOut); |
|||
|
|||
// set 1s fallback in case transition event doesn't fire
|
|||
clearTimeout( this.__internal.timerOut ); |
|||
this.__internal.timerOut = setTimeout( this.__internal.transitionOutHandler, transition.supported ? 1000 : 100 ); |
|||
// hide dialog
|
|||
addClass(this.elements.root, classes.hidden); |
|||
//reflow
|
|||
reflow = this.elements.modal.offsetWidth; |
|||
|
|||
// remove custom dialog class on hide
|
|||
if (typeof this.__internal.className !== 'undefined' && this.__internal.className !== '') { |
|||
removeClass(this.elements.root, this.__internal.className); |
|||
} |
|||
|
|||
// internal on close event
|
|||
if(typeof this.hooks.onclose === 'function'){ |
|||
this.hooks.onclose.call(this); |
|||
} |
|||
|
|||
// allow custom `onclose` method
|
|||
dispatchEvent('onclose', this); |
|||
|
|||
//remove from open dialogs
|
|||
openDialogs.splice(openDialogs.indexOf(this),1); |
|||
this.__internal.isOpen = false; |
|||
|
|||
ensureNoOverflow(); |
|||
} |
|||
|
|||
} |
|||
// last dialog and tab index was set by us, remove it.
|
|||
if(!openDialogs.length && tabindex === '0'){ |
|||
document.body.removeAttribute('tabindex'); |
|||
} |
|||
return this; |
|||
}, |
|||
/** |
|||
* Close all open dialogs except this. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
closeOthers:function(){ |
|||
alertify.closeAll(this); |
|||
return this; |
|||
}, |
|||
/** |
|||
* Destroys this dialog instance |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
destroy:function(){ |
|||
if(this.__internal) { |
|||
if (this.__internal.isOpen ) { |
|||
//mark dialog for destruction, this will be called on tranistionOut event.
|
|||
this.__internal.destroy = function(){ |
|||
destruct(this, initialize); |
|||
}; |
|||
//close the dialog to unbind all events.
|
|||
this.close(); |
|||
}else if(!this.__internal.destroy){ |
|||
destruct(this, initialize); |
|||
} |
|||
} |
|||
return this; |
|||
}, |
|||
}; |
@ -0,0 +1,201 @@ |
|||
/** |
|||
* Bind dialogs events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function bindEvents(instance) { |
|||
// if first dialog, hook global handlers
|
|||
if (openDialogs.length === 1) { |
|||
//global
|
|||
on(window, 'resize', windowResize); |
|||
on(document.body, 'keyup', keyupHandler); |
|||
on(document.body, 'keydown', keydownHandler); |
|||
on(document.body, 'focus', onReset); |
|||
|
|||
//move
|
|||
on(document.documentElement, 'mousemove', move); |
|||
on(document.documentElement, 'touchmove', move); |
|||
on(document.documentElement, 'mouseup', endMove); |
|||
on(document.documentElement, 'touchend', endMove); |
|||
//resize
|
|||
on(document.documentElement, 'mousemove', resize); |
|||
on(document.documentElement, 'touchmove', resize); |
|||
on(document.documentElement, 'mouseup', endResize); |
|||
on(document.documentElement, 'touchend', endResize); |
|||
} |
|||
|
|||
// common events
|
|||
on(instance.elements.commands.container, 'click', instance.__internal.commandsClickHandler); |
|||
on(instance.elements.footer, 'click', instance.__internal.buttonsClickHandler); |
|||
on(instance.elements.reset[0], 'focusin', instance.__internal.resetHandler); |
|||
on(instance.elements.reset[0], 'keydown', recycleTab); |
|||
on(instance.elements.reset[1], 'focusin', instance.__internal.resetHandler); |
|||
|
|||
//prevent handling key up when dialog is being opened by a key stroke.
|
|||
cancelKeyup = true; |
|||
// hook in transition handler
|
|||
on(instance.elements.dialog, transition.type, instance.__internal.transitionInHandler); |
|||
|
|||
// modelss only events
|
|||
if (!instance.get('modal')) { |
|||
bindModelessEvents(instance); |
|||
} |
|||
|
|||
// resizable
|
|||
if (instance.get('resizable')) { |
|||
bindResizableEvents(instance); |
|||
} |
|||
|
|||
// movable
|
|||
if (instance.get('movable')) { |
|||
bindMovableEvents(instance); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Unbind dialogs events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function unbindEvents(instance) { |
|||
// if last dialog, remove global handlers
|
|||
if (openDialogs.length === 1) { |
|||
//global
|
|||
off(window, 'resize', windowResize); |
|||
off(document.body, 'keyup', keyupHandler); |
|||
off(document.body, 'keydown', keydownHandler); |
|||
off(document.body, 'focus', onReset); |
|||
//move
|
|||
off(document.documentElement, 'mousemove', move); |
|||
off(document.documentElement, 'mouseup', endMove); |
|||
//resize
|
|||
off(document.documentElement, 'mousemove', resize); |
|||
off(document.documentElement, 'mouseup', endResize); |
|||
} |
|||
|
|||
// common events
|
|||
off(instance.elements.commands.container, 'click', instance.__internal.commandsClickHandler); |
|||
off(instance.elements.footer, 'click', instance.__internal.buttonsClickHandler); |
|||
off(instance.elements.reset[0], 'focusin', instance.__internal.resetHandler); |
|||
off(instance.elements.reset[0], 'keydown', recycleTab); |
|||
off(instance.elements.reset[1], 'focusin', instance.__internal.resetHandler); |
|||
|
|||
// hook out transition handler
|
|||
on(instance.elements.dialog, transition.type, instance.__internal.transitionOutHandler); |
|||
|
|||
// modelss only events
|
|||
if (!instance.get('modal')) { |
|||
unbindModelessEvents(instance); |
|||
} |
|||
|
|||
// movable
|
|||
if (instance.get('movable')) { |
|||
unbindMovableEvents(instance); |
|||
} |
|||
|
|||
// resizable
|
|||
if (instance.get('resizable')) { |
|||
unbindResizableEvents(instance); |
|||
} |
|||
|
|||
} |
|||
|
|||
/** |
|||
* Bind modeless specific events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function bindModelessEvents(instance) { |
|||
on(instance.elements.dialog, 'focus', instance.__internal.bringToFrontHandler, true); |
|||
} |
|||
|
|||
/** |
|||
* Unbind modeless specific events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function unbindModelessEvents(instance) { |
|||
off(instance.elements.dialog, 'focus', instance.__internal.bringToFrontHandler, true); |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* Bind movable specific events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function bindMovableEvents(instance) { |
|||
on(instance.elements.header, 'mousedown', instance.__internal.beginMoveHandler); |
|||
on(instance.elements.header, 'touchstart', instance.__internal.beginMoveHandler); |
|||
} |
|||
|
|||
/** |
|||
* Unbind movable specific events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function unbindMovableEvents(instance) { |
|||
off(instance.elements.header, 'mousedown', instance.__internal.beginMoveHandler); |
|||
off(instance.elements.header, 'touchstart', instance.__internal.beginMoveHandler); |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* Bind resizable specific events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function bindResizableEvents(instance) { |
|||
on(instance.elements.resizeHandle, 'mousedown', instance.__internal.beginResizeHandler); |
|||
on(instance.elements.resizeHandle, 'touchstart', instance.__internal.beginResizeHandler); |
|||
} |
|||
|
|||
/** |
|||
* Unbind resizable specific events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function unbindResizableEvents(instance) { |
|||
off(instance.elements.resizeHandle, 'mousedown', instance.__internal.beginResizeHandler); |
|||
off(instance.elements.resizeHandle, 'touchstart', instance.__internal.beginResizeHandler); |
|||
} |
|||
|
|||
/** |
|||
* Bind closable events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function bindClosableEvents(instance) { |
|||
on(instance.elements.modal, 'click', instance.__internal.modalClickHandler); |
|||
} |
|||
|
|||
/** |
|||
* Unbind closable specific events |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function unbindClosableEvents(instance) { |
|||
off(instance.elements.modal, 'click', instance.__internal.modalClickHandler); |
|||
} |
@ -0,0 +1,122 @@ |
|||
/** |
|||
* Sets focus to proper dialog element |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {Node} [resetTarget=undefined] DOM element to reset focus to. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function setFocus(instance, resetTarget) { |
|||
// reset target has already been determined.
|
|||
if (resetTarget) { |
|||
resetTarget.focus(); |
|||
} else { |
|||
// current instance focus settings
|
|||
var focus = instance.__internal.focus; |
|||
// the focus element.
|
|||
var element = focus.element; |
|||
|
|||
switch (typeof focus.element) { |
|||
// a number means a button index
|
|||
case 'number': |
|||
if (instance.__internal.buttons.length > focus.element) { |
|||
//in basic view, skip focusing the buttons.
|
|||
if (instance.get('basic') === true) { |
|||
element = instance.elements.reset[0]; |
|||
} else { |
|||
element = instance.__internal.buttons[focus.element].element; |
|||
} |
|||
} |
|||
break; |
|||
// a string means querySelector to select from dialog body contents.
|
|||
case 'string': |
|||
element = instance.elements.body.querySelector(focus.element); |
|||
break; |
|||
// a function should return the focus element.
|
|||
case 'function': |
|||
element = focus.element.call(instance); |
|||
break; |
|||
} |
|||
|
|||
// if no focus element, default to first reset element.
|
|||
if (instance.get('defaultFocusOff') === true || ((typeof element === 'undefined' || element === null) && instance.__internal.buttons.length === 0)) { |
|||
element = instance.elements.reset[0]; |
|||
} |
|||
// focus
|
|||
if (element && element.focus) { |
|||
element.focus(); |
|||
// if selectable
|
|||
if (focus.select && element.select) { |
|||
element.select(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Focus event handler, attached to document.body and dialogs own reset links. |
|||
* handles the focus for modal dialogs only. |
|||
* |
|||
* @param {Event} event DOM focus event object. |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function onReset(event, instance) { |
|||
|
|||
// should work on last modal if triggered from document.body
|
|||
if (!instance) { |
|||
for (var x = openDialogs.length - 1; x > -1; x -= 1) { |
|||
if (openDialogs[x].isModal()) { |
|||
instance = openDialogs[x]; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if(instance) { |
|||
// if modal
|
|||
if (instance.isModal()) { |
|||
// determine reset target to enable forward/backward tab cycle.
|
|||
var firstReset = instance.elements.reset[0], |
|||
lastReset = instance.elements.reset[1], |
|||
lastFocusedElement = event.relatedTarget, |
|||
within = instance.elements.root.contains(lastFocusedElement), |
|||
target = event.srcElement || event.target, |
|||
resetTarget; |
|||
|
|||
//if the previous focused element element was outside the modal do nthing
|
|||
if( /*first show */ |
|||
(target === firstReset && !within) || |
|||
/*focus cycle */ |
|||
(target === lastReset && lastFocusedElement == firstReset)) |
|||
return |
|||
else if(target === lastReset || target === document.body) |
|||
resetTarget = firstReset |
|||
else if(target === firstReset && lastFocusedElement == lastReset){ |
|||
resetTarget = findTabbable(instance) |
|||
}else if(target == firstReset && within){ |
|||
resetTarget = findTabbable(instance, true) |
|||
} |
|||
// focus
|
|||
setFocus(instance, resetTarget); |
|||
} |
|||
} |
|||
} |
|||
function findTabbable(instance, last){ |
|||
var tabbables = [].slice.call(instance.elements.dialog.querySelectorAll(defaults.tabbable)); |
|||
last && tabbables.reverse() |
|||
for(var x=0;x<tabbables.length;x++){ |
|||
var tabbable = tabbables[x] |
|||
//check if visible
|
|||
if(!!(tabbable.offsetParent || tabbable.offsetWidth || tabbable.offsetHeight || tabbable.getClientRects().length)){ |
|||
return tabbable |
|||
} |
|||
} |
|||
} |
|||
function recycleTab(event) { |
|||
var instance = openDialogs[openDialogs.length - 1]; |
|||
if (instance && event.shiftKey && event.keyCode === keys.TAB) { |
|||
instance.elements.reset[1].focus() |
|||
} |
|||
} |
@ -0,0 +1,609 @@ |
|||
/** |
|||
* Super class for all dialogs |
|||
* |
|||
* @return {Object} base dialog prototype |
|||
*/ |
|||
var dialog = (function () { |
|||
var //holds the list of used keys.
|
|||
usedKeys = [], |
|||
//dummy variable, used to trigger dom reflow.
|
|||
reflow = null, |
|||
//holds body tab index in case it has any.
|
|||
tabindex = false, |
|||
//condition for detecting safari
|
|||
isSafari = window.navigator.userAgent.indexOf('Safari') > -1 && window.navigator.userAgent.indexOf('Chrome') < 0, |
|||
//dialog building blocks
|
|||
templates = { |
|||
dimmer:'<div class="ajs-dimmer"></div>', |
|||
/*tab index required to fire click event before body focus*/ |
|||
modal: '<div class="ajs-modal" tabindex="0"></div>', |
|||
dialog: '<div class="ajs-dialog" tabindex="0"></div>', |
|||
reset: '<button class="ajs-reset"></button>', |
|||
commands: '<div class="ajs-commands"><button class="ajs-pin"></button><button class="ajs-maximize"></button><button class="ajs-close"></button></div>', |
|||
header: '<div class="ajs-header"></div>', |
|||
body: '<div class="ajs-body"></div>', |
|||
content: '<div class="ajs-content"></div>', |
|||
footer: '<div class="ajs-footer"></div>', |
|||
buttons: { primary: '<div class="ajs-primary ajs-buttons"></div>', auxiliary: '<div class="ajs-auxiliary ajs-buttons"></div>' }, |
|||
button: '<button class="ajs-button"></button>', |
|||
resizeHandle: '<div class="ajs-handle"></div>', |
|||
}, |
|||
//common class names
|
|||
classes = { |
|||
animationIn: 'ajs-in', |
|||
animationOut: 'ajs-out', |
|||
base: 'alertify', |
|||
basic:'ajs-basic', |
|||
capture: 'ajs-capture', |
|||
closable:'ajs-closable', |
|||
fixed: 'ajs-fixed', |
|||
frameless:'ajs-frameless', |
|||
hidden: 'ajs-hidden', |
|||
maximize: 'ajs-maximize', |
|||
maximized: 'ajs-maximized', |
|||
maximizable:'ajs-maximizable', |
|||
modeless: 'ajs-modeless', |
|||
movable: 'ajs-movable', |
|||
noSelection: 'ajs-no-selection', |
|||
noOverflow: 'ajs-no-overflow', |
|||
noPadding:'ajs-no-padding', |
|||
pin:'ajs-pin', |
|||
pinnable:'ajs-pinnable', |
|||
prefix: 'ajs-', |
|||
resizable: 'ajs-resizable', |
|||
restore: 'ajs-restore', |
|||
shake:'ajs-shake', |
|||
unpinned:'ajs-unpinned', |
|||
}; |
|||
|
|||
/** |
|||
* Helper: initializes the dialog instance |
|||
* |
|||
* @return {Number} The total count of currently open modals. |
|||
*/ |
|||
function initialize(instance){ |
|||
|
|||
if(!instance.__internal){ |
|||
//invoke preinit global hook
|
|||
alertify.defaults.hooks.preinit(instance); |
|||
//no need to expose init after this.
|
|||
delete instance.__init; |
|||
|
|||
//keep a copy of initial dialog settings
|
|||
if(!instance.__settings){ |
|||
instance.__settings = copy(instance.settings); |
|||
} |
|||
|
|||
//get dialog buttons/focus setup
|
|||
var setup; |
|||
if(typeof instance.setup === 'function'){ |
|||
setup = instance.setup(); |
|||
setup.options = setup.options || {}; |
|||
setup.focus = setup.focus || {}; |
|||
}else{ |
|||
setup = { |
|||
buttons:[], |
|||
focus:{ |
|||
element:null, |
|||
select:false |
|||
}, |
|||
options:{ |
|||
} |
|||
}; |
|||
} |
|||
|
|||
//initialize hooks object.
|
|||
if(typeof instance.hooks !== 'object'){ |
|||
instance.hooks = {}; |
|||
} |
|||
|
|||
//copy buttons defintion
|
|||
var buttonsDefinition = []; |
|||
if(Array.isArray(setup.buttons)){ |
|||
for(var b=0;b<setup.buttons.length;b+=1){ |
|||
var ref = setup.buttons[b], |
|||
cpy = {}; |
|||
for (var i in ref) { |
|||
if (ref.hasOwnProperty(i)) { |
|||
cpy[i] = ref[i]; |
|||
} |
|||
} |
|||
buttonsDefinition.push(cpy); |
|||
} |
|||
} |
|||
|
|||
var internal = instance.__internal = { |
|||
/** |
|||
* Flag holding the open state of the dialog |
|||
* |
|||
* @type {Boolean} |
|||
*/ |
|||
isOpen:false, |
|||
/** |
|||
* Active element is the element that will receive focus after |
|||
* closing the dialog. It defaults as the body tag, but gets updated |
|||
* to the last focused element before the dialog was opened. |
|||
* |
|||
* @type {Node} |
|||
*/ |
|||
activeElement:document.body, |
|||
timerIn:undefined, |
|||
timerOut:undefined, |
|||
buttons: buttonsDefinition, |
|||
focus: setup.focus, |
|||
options: { |
|||
title: undefined, |
|||
modal: undefined, |
|||
basic:undefined, |
|||
frameless:undefined, |
|||
defaultFocusOff:undefined, |
|||
pinned: undefined, |
|||
movable: undefined, |
|||
moveBounded:undefined, |
|||
resizable: undefined, |
|||
autoReset: undefined, |
|||
closable: undefined, |
|||
closableByDimmer: undefined, |
|||
invokeOnCloseOff:undefined, |
|||
maximizable: undefined, |
|||
startMaximized: undefined, |
|||
pinnable: undefined, |
|||
transition: undefined, |
|||
padding:undefined, |
|||
overflow:undefined, |
|||
onshow:undefined, |
|||
onclosing:undefined, |
|||
onclose:undefined, |
|||
onfocus:undefined, |
|||
onmove:undefined, |
|||
onmoved:undefined, |
|||
onresize:undefined, |
|||
onresized:undefined, |
|||
onmaximize:undefined, |
|||
onmaximized:undefined, |
|||
onrestore:undefined, |
|||
onrestored:undefined |
|||
}, |
|||
resetHandler:undefined, |
|||
beginMoveHandler:undefined, |
|||
beginResizeHandler:undefined, |
|||
bringToFrontHandler:undefined, |
|||
modalClickHandler:undefined, |
|||
buttonsClickHandler:undefined, |
|||
commandsClickHandler:undefined, |
|||
transitionInHandler:undefined, |
|||
transitionOutHandler:undefined, |
|||
destroy:undefined |
|||
}; |
|||
|
|||
var elements = {}; |
|||
//root node
|
|||
elements.root = document.createElement('div'); |
|||
//prevent FOUC in case of async styles loading.
|
|||
elements.root.style.display = 'none'; |
|||
elements.root.className = classes.base + ' ' + classes.hidden + ' '; |
|||
|
|||
elements.root.innerHTML = templates.dimmer + templates.modal; |
|||
|
|||
//dimmer
|
|||
elements.dimmer = elements.root.firstChild; |
|||
|
|||
//dialog
|
|||
elements.modal = elements.root.lastChild; |
|||
elements.modal.innerHTML = templates.dialog; |
|||
elements.dialog = elements.modal.firstChild; |
|||
elements.dialog.innerHTML = templates.reset + templates.commands + templates.header + templates.body + templates.footer + templates.resizeHandle + templates.reset; |
|||
|
|||
//reset links
|
|||
elements.reset = []; |
|||
elements.reset.push(elements.dialog.firstChild); |
|||
elements.reset.push(elements.dialog.lastChild); |
|||
|
|||
//commands
|
|||
elements.commands = {}; |
|||
elements.commands.container = elements.reset[0].nextSibling; |
|||
elements.commands.pin = elements.commands.container.firstChild; |
|||
elements.commands.maximize = elements.commands.pin.nextSibling; |
|||
elements.commands.close = elements.commands.maximize.nextSibling; |
|||
|
|||
//header
|
|||
elements.header = elements.commands.container.nextSibling; |
|||
|
|||
//body
|
|||
elements.body = elements.header.nextSibling; |
|||
elements.body.innerHTML = templates.content; |
|||
elements.content = elements.body.firstChild; |
|||
|
|||
//footer
|
|||
elements.footer = elements.body.nextSibling; |
|||
elements.footer.innerHTML = templates.buttons.auxiliary + templates.buttons.primary; |
|||
|
|||
//resize handle
|
|||
elements.resizeHandle = elements.footer.nextSibling; |
|||
|
|||
//buttons
|
|||
elements.buttons = {}; |
|||
elements.buttons.auxiliary = elements.footer.firstChild; |
|||
elements.buttons.primary = elements.buttons.auxiliary.nextSibling; |
|||
elements.buttons.primary.innerHTML = templates.button; |
|||
elements.buttonTemplate = elements.buttons.primary.firstChild; |
|||
//remove button template
|
|||
elements.buttons.primary.removeChild(elements.buttonTemplate); |
|||
|
|||
for(var x=0; x < instance.__internal.buttons.length; x+=1) { |
|||
var button = instance.__internal.buttons[x]; |
|||
|
|||
// add to the list of used keys.
|
|||
if(usedKeys.indexOf(button.key) < 0){ |
|||
usedKeys.push(button.key); |
|||
} |
|||
|
|||
button.element = elements.buttonTemplate.cloneNode(); |
|||
button.element.innerHTML = button.text; |
|||
if(typeof button.className === 'string' && button.className !== ''){ |
|||
addClass(button.element, button.className); |
|||
} |
|||
for(var key in button.attrs){ |
|||
if(key !== 'className' && button.attrs.hasOwnProperty(key)){ |
|||
button.element.setAttribute(key, button.attrs[key]); |
|||
} |
|||
} |
|||
if(button.scope === 'auxiliary'){ |
|||
elements.buttons.auxiliary.appendChild(button.element); |
|||
}else{ |
|||
elements.buttons.primary.appendChild(button.element); |
|||
} |
|||
} |
|||
//make elements pubic
|
|||
instance.elements = elements; |
|||
|
|||
//save event handlers delegates
|
|||
internal.resetHandler = delegate(instance, onReset); |
|||
internal.beginMoveHandler = delegate(instance, beginMove); |
|||
internal.beginResizeHandler = delegate(instance, beginResize); |
|||
internal.bringToFrontHandler = delegate(instance, bringToFront); |
|||
internal.modalClickHandler = delegate(instance, modalClickHandler); |
|||
internal.buttonsClickHandler = delegate(instance, buttonsClickHandler); |
|||
internal.commandsClickHandler = delegate(instance, commandsClickHandler); |
|||
internal.transitionInHandler = delegate(instance, handleTransitionInEvent); |
|||
internal.transitionOutHandler = delegate(instance, handleTransitionOutEvent); |
|||
|
|||
//settings
|
|||
for(var opKey in internal.options){ |
|||
if(setup.options[opKey] !== undefined){ |
|||
// if found in user options
|
|||
instance.set(opKey, setup.options[opKey]); |
|||
}else if(alertify.defaults.hasOwnProperty(opKey)) { |
|||
// else if found in defaults options
|
|||
instance.set(opKey, alertify.defaults[opKey]); |
|||
}else if(opKey === 'title' ) { |
|||
// else if title key, use alertify.defaults.glossary
|
|||
instance.set(opKey, alertify.defaults.glossary[opKey]); |
|||
} |
|||
} |
|||
|
|||
// allow dom customization
|
|||
if(typeof instance.build === 'function'){ |
|||
instance.build(); |
|||
} |
|||
|
|||
//invoke postinit global hook
|
|||
alertify.defaults.hooks.postinit(instance); |
|||
} |
|||
|
|||
//add to the end of the DOM tree.
|
|||
document.body.appendChild(instance.elements.root); |
|||
} |
|||
|
|||
/** |
|||
* Helper: maintains scroll position |
|||
* |
|||
*/ |
|||
var scrollX, scrollY; |
|||
function saveScrollPosition(){ |
|||
scrollX = getScrollLeft(); |
|||
scrollY = getScrollTop(); |
|||
} |
|||
function restoreScrollPosition(){ |
|||
window.scrollTo(scrollX, scrollY); |
|||
} |
|||
|
|||
/** |
|||
* Helper: adds/removes no-overflow class from body |
|||
* |
|||
*/ |
|||
function ensureNoOverflow(){ |
|||
var requiresNoOverflow = 0; |
|||
for(var x=0;x<openDialogs.length;x+=1){ |
|||
var instance = openDialogs[x]; |
|||
if(instance.isModal() || instance.isMaximized()){ |
|||
requiresNoOverflow+=1; |
|||
} |
|||
} |
|||
if(requiresNoOverflow === 0 && document.body.className.indexOf(classes.noOverflow) >= 0){ |
|||
//last open modal or last maximized one
|
|||
removeClass(document.body, classes.noOverflow); |
|||
preventBodyShift(false); |
|||
}else if(requiresNoOverflow > 0 && document.body.className.indexOf(classes.noOverflow) < 0){ |
|||
//first open modal or first maximized one
|
|||
preventBodyShift(true); |
|||
addClass(document.body, classes.noOverflow); |
|||
} |
|||
} |
|||
var top = '', topScroll = 0; |
|||
/** |
|||
* Helper: prevents body shift. |
|||
* |
|||
*/ |
|||
function preventBodyShift(add){ |
|||
if(alertify.defaults.preventBodyShift){ |
|||
if(add && document.documentElement.scrollHeight > document.documentElement.clientHeight ){//&& openDialogs[openDialogs.length-1].elements.dialog.clientHeight <= document.documentElement.clientHeight){
|
|||
topScroll = scrollY; |
|||
top = window.getComputedStyle(document.body).top; |
|||
addClass(document.body, classes.fixed); |
|||
document.body.style.top = -scrollY + 'px'; |
|||
} else if(!add) { |
|||
scrollY = topScroll; |
|||
document.body.style.top = top; |
|||
removeClass(document.body, classes.fixed); |
|||
restoreScrollPosition(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Sets the name of the transition used to show/hide the dialog |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
*/ |
|||
function updateTransition(instance, value, oldValue){ |
|||
if(typeof oldValue === 'string'){ |
|||
removeClass(instance.elements.root,classes.prefix + oldValue); |
|||
} |
|||
addClass(instance.elements.root, classes.prefix + value); |
|||
reflow = instance.elements.root.offsetWidth; |
|||
} |
|||
|
|||
/** |
|||
* Toggles the dialog display mode |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updateDisplayMode(instance){ |
|||
if(instance.get('modal')){ |
|||
|
|||
//make modal
|
|||
removeClass(instance.elements.root, classes.modeless); |
|||
|
|||
//only if open
|
|||
if(instance.isOpen()){ |
|||
unbindModelessEvents(instance); |
|||
|
|||
//in case a pinned modless dialog was made modal while open.
|
|||
updateAbsPositionFix(instance); |
|||
|
|||
ensureNoOverflow(); |
|||
} |
|||
}else{ |
|||
//make modelss
|
|||
addClass(instance.elements.root, classes.modeless); |
|||
|
|||
//only if open
|
|||
if(instance.isOpen()){ |
|||
bindModelessEvents(instance); |
|||
|
|||
//in case pin/unpin was called while a modal is open
|
|||
updateAbsPositionFix(instance); |
|||
|
|||
ensureNoOverflow(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Toggles the dialog basic view mode |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updateBasicMode(instance){ |
|||
if (instance.get('basic')) { |
|||
// add class
|
|||
addClass(instance.elements.root, classes.basic); |
|||
} else { |
|||
// remove class
|
|||
removeClass(instance.elements.root, classes.basic); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Toggles the dialog frameless view mode |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updateFramelessMode(instance){ |
|||
if (instance.get('frameless')) { |
|||
// add class
|
|||
addClass(instance.elements.root, classes.frameless); |
|||
} else { |
|||
// remove class
|
|||
removeClass(instance.elements.root, classes.frameless); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Helper: Brings the modeless dialog to front, attached to modeless dialogs. |
|||
* |
|||
* @param {Event} event Focus event |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function bringToFront(event, instance){ |
|||
|
|||
// Do not bring to front if preceeded by an open modal
|
|||
var index = openDialogs.indexOf(instance); |
|||
for(var x=index+1;x<openDialogs.length;x+=1){ |
|||
if(openDialogs[x].isModal()){ |
|||
return; |
|||
} |
|||
} |
|||
|
|||
// Bring to front by making it the last child.
|
|||
if(document.body.lastChild !== instance.elements.root){ |
|||
document.body.appendChild(instance.elements.root); |
|||
//also make sure its at the end of the list
|
|||
openDialogs.splice(openDialogs.indexOf(instance),1); |
|||
openDialogs.push(instance); |
|||
setFocus(instance); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* Helper: reflects dialogs options updates |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {String} option The updated option name. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function optionUpdated(instance, option, oldValue, newValue){ |
|||
switch(option){ |
|||
case 'title': |
|||
instance.setHeader(newValue); |
|||
break; |
|||
case 'modal': |
|||
updateDisplayMode(instance); |
|||
break; |
|||
case 'basic': |
|||
updateBasicMode(instance); |
|||
break; |
|||
case 'frameless': |
|||
updateFramelessMode(instance); |
|||
break; |
|||
case 'pinned': |
|||
updatePinned(instance); |
|||
break; |
|||
case 'closable': |
|||
updateClosable(instance); |
|||
break; |
|||
case 'maximizable': |
|||
updateMaximizable(instance); |
|||
break; |
|||
case 'pinnable': |
|||
updatePinnable(instance); |
|||
break; |
|||
case 'movable': |
|||
updateMovable(instance); |
|||
break; |
|||
case 'resizable': |
|||
updateResizable(instance); |
|||
break; |
|||
case 'padding': |
|||
if(newValue){ |
|||
removeClass(instance.elements.root, classes.noPadding); |
|||
}else if(instance.elements.root.className.indexOf(classes.noPadding) < 0){ |
|||
addClass(instance.elements.root, classes.noPadding); |
|||
} |
|||
break; |
|||
case 'overflow': |
|||
if(newValue){ |
|||
removeClass(instance.elements.root, classes.noOverflow); |
|||
}else if(instance.elements.root.className.indexOf(classes.noOverflow) < 0){ |
|||
addClass(instance.elements.root, classes.noOverflow); |
|||
} |
|||
break; |
|||
case 'transition': |
|||
updateTransition(instance,newValue, oldValue); |
|||
break; |
|||
} |
|||
|
|||
// internal on option updated event
|
|||
if(typeof instance.hooks.onupdate === 'function'){ |
|||
instance.hooks.onupdate.call(instance, option, oldValue, newValue); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Helper: reflects dialogs options updates |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {Object} obj The object to set/get a value on/from. |
|||
* @param {Function} callback The callback function to call if the key was found. |
|||
* @param {String|Object} key A string specifying a propery name or a collection of key value pairs. |
|||
* @param {Object} value Optional, the value associated with the key (in case it was a string). |
|||
* @param {String} option The updated option name. |
|||
* |
|||
* @return {Object} result object |
|||
* The result objects has an 'op' property, indicating of this is a SET or GET operation. |
|||
* GET: |
|||
* - found: a flag indicating if the key was found or not. |
|||
* - value: the property value. |
|||
* SET: |
|||
* - items: a list of key value pairs of the properties being set. |
|||
* each contains: |
|||
* - found: a flag indicating if the key was found or not. |
|||
* - key: the property key. |
|||
* - value: the property value. |
|||
*/ |
|||
function update(instance, obj, callback, key, value){ |
|||
var result = {op:undefined, items: [] }; |
|||
if(typeof value === 'undefined' && typeof key === 'string') { |
|||
//get
|
|||
result.op = 'get'; |
|||
if(obj.hasOwnProperty(key)){ |
|||
result.found = true; |
|||
result.value = obj[key]; |
|||
}else{ |
|||
result.found = false; |
|||
result.value = undefined; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
var old; |
|||
//set
|
|||
result.op = 'set'; |
|||
if(typeof key === 'object'){ |
|||
//set multiple
|
|||
var args = key; |
|||
for (var prop in args) { |
|||
if (obj.hasOwnProperty(prop)) { |
|||
if(obj[prop] !== args[prop]){ |
|||
old = obj[prop]; |
|||
obj[prop] = args[prop]; |
|||
callback.call(instance,prop, old, args[prop]); |
|||
} |
|||
result.items.push({ 'key': prop, 'value': args[prop], 'found':true}); |
|||
}else{ |
|||
result.items.push({ 'key': prop, 'value': args[prop], 'found':false}); |
|||
} |
|||
} |
|||
} else if (typeof key === 'string'){ |
|||
//set single
|
|||
if (obj.hasOwnProperty(key)) { |
|||
if(obj[key] !== value){ |
|||
old = obj[key]; |
|||
obj[key] = value; |
|||
callback.call(instance,key, old, value); |
|||
} |
|||
result.items.push({'key': key, 'value': value , 'found':true}); |
|||
|
|||
}else{ |
|||
result.items.push({'key': key, 'value': value , 'found':false}); |
|||
} |
|||
} else { |
|||
//invalid params
|
|||
throw new Error('args must be a string or object'); |
|||
} |
|||
} |
|||
return result; |
|||
} |
@ -0,0 +1,215 @@ |
|||
/* Controls moving a dialog around */ |
|||
//holde the current moving instance
|
|||
var movable = null, |
|||
//holds the current X offset when move starts
|
|||
offsetX = 0, |
|||
//holds the current Y offset when move starts
|
|||
offsetY = 0, |
|||
xProp = 'pageX', |
|||
yProp = 'pageY', |
|||
bounds = null, |
|||
refreshTop = false, |
|||
moveDelegate = null |
|||
; |
|||
|
|||
/** |
|||
* Helper: sets the element top/left coordinates |
|||
* |
|||
* @param {Event} event DOM event object. |
|||
* @param {Node} element The element being moved. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function moveElement(event, element) { |
|||
var left = (event[xProp] - offsetX), |
|||
top = (event[yProp] - offsetY); |
|||
|
|||
if(refreshTop){ |
|||
top -= document.body.scrollTop; |
|||
} |
|||
|
|||
element.style.left = left + 'px'; |
|||
element.style.top = top + 'px'; |
|||
|
|||
} |
|||
/** |
|||
* Helper: sets the element top/left coordinates within screen bounds |
|||
* |
|||
* @param {Event} event DOM event object. |
|||
* @param {Node} element The element being moved. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function moveElementBounded(event, element) { |
|||
var left = (event[xProp] - offsetX), |
|||
top = (event[yProp] - offsetY); |
|||
|
|||
if(refreshTop){ |
|||
top -= document.body.scrollTop; |
|||
} |
|||
|
|||
element.style.left = Math.min(bounds.maxLeft, Math.max(bounds.minLeft, left)) + 'px'; |
|||
if(refreshTop){ |
|||
element.style.top = Math.min(bounds.maxTop, Math.max(bounds.minTop, top)) + 'px'; |
|||
}else{ |
|||
element.style.top = Math.max(bounds.minTop, top) + 'px'; |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Triggers the start of a move event, attached to the header element mouse down event. |
|||
* Adds no-selection class to the body, disabling selection while moving. |
|||
* |
|||
* @param {Event} event DOM event object. |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {Boolean} false |
|||
*/ |
|||
function beginMove(event, instance) { |
|||
if (resizable === null && !instance.isMaximized() && instance.get('movable')) { |
|||
var eventSrc, left=0, top=0; |
|||
if (event.type === 'touchstart') { |
|||
event.preventDefault(); |
|||
eventSrc = event.targetTouches[0]; |
|||
xProp = 'clientX'; |
|||
yProp = 'clientY'; |
|||
} else if (event.button === 0) { |
|||
eventSrc = event; |
|||
} |
|||
|
|||
if (eventSrc) { |
|||
|
|||
var element = instance.elements.dialog; |
|||
addClass(element, classes.capture); |
|||
|
|||
if (element.style.left) { |
|||
left = parseInt(element.style.left, 10); |
|||
} |
|||
|
|||
if (element.style.top) { |
|||
top = parseInt(element.style.top, 10); |
|||
} |
|||
|
|||
offsetX = eventSrc[xProp] - left; |
|||
offsetY = eventSrc[yProp] - top; |
|||
|
|||
if(instance.isModal()){ |
|||
offsetY += instance.elements.modal.scrollTop; |
|||
}else if(instance.isPinned()){ |
|||
offsetY -= document.body.scrollTop; |
|||
} |
|||
|
|||
if(instance.get('moveBounded')){ |
|||
var current = element, |
|||
offsetLeft = -left, |
|||
offsetTop = -top; |
|||
|
|||
//calc offset
|
|||
do { |
|||
offsetLeft += current.offsetLeft; |
|||
offsetTop += current.offsetTop; |
|||
} while (current = current.offsetParent); |
|||
|
|||
bounds = { |
|||
maxLeft : offsetLeft, |
|||
minLeft : -offsetLeft, |
|||
maxTop : document.documentElement.clientHeight - element.clientHeight - offsetTop, |
|||
minTop : -offsetTop |
|||
}; |
|||
moveDelegate = moveElementBounded; |
|||
}else{ |
|||
bounds = null; |
|||
moveDelegate = moveElement; |
|||
} |
|||
|
|||
// allow custom `onmove` method
|
|||
dispatchEvent('onmove', instance); |
|||
|
|||
refreshTop = !instance.isModal() && instance.isPinned(); |
|||
movable = instance; |
|||
moveDelegate(eventSrc, element); |
|||
addClass(document.body, classes.noSelection); |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* The actual move handler, attached to document.body mousemove event. |
|||
* |
|||
* @param {Event} event DOM event object. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function move(event) { |
|||
if (movable) { |
|||
var eventSrc; |
|||
if (event.type === 'touchmove') { |
|||
event.preventDefault(); |
|||
eventSrc = event.targetTouches[0]; |
|||
} else if (event.button === 0) { |
|||
eventSrc = event; |
|||
} |
|||
if (eventSrc) { |
|||
moveDelegate(eventSrc, movable.elements.dialog); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Triggers the end of a move event, attached to document.body mouseup event. |
|||
* Removes no-selection class from document.body, allowing selection. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function endMove() { |
|||
if (movable) { |
|||
var instance = movable; |
|||
movable = bounds = null; |
|||
removeClass(document.body, classes.noSelection); |
|||
removeClass(instance.elements.dialog, classes.capture); |
|||
// allow custom `onmoved` method
|
|||
dispatchEvent('onmoved', instance); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Resets any changes made by moving the element to its original state, |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function resetMove(instance) { |
|||
movable = null; |
|||
var element = instance.elements.dialog; |
|||
element.style.left = element.style.top = ''; |
|||
} |
|||
|
|||
/** |
|||
* Updates the dialog move behavior. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {Boolean} on True to add the behavior, removes it otherwise. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updateMovable(instance) { |
|||
if (instance.get('movable')) { |
|||
// add class
|
|||
addClass(instance.elements.root, classes.movable); |
|||
if (instance.isOpen()) { |
|||
bindMovableEvents(instance); |
|||
} |
|||
} else { |
|||
|
|||
//reset
|
|||
resetMove(instance); |
|||
// remove class
|
|||
removeClass(instance.elements.root, classes.movable); |
|||
if (instance.isOpen()) { |
|||
unbindMovableEvents(instance); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1 @@ |
|||
} () ); |
@ -0,0 +1,220 @@ |
|||
/* Controls moving a dialog around */ |
|||
//holde the current instance being resized
|
|||
var resizable = null, |
|||
//holds the staring left offset when resize starts.
|
|||
startingLeft = Number.Nan, |
|||
//holds the staring width when resize starts.
|
|||
startingWidth = 0, |
|||
//holds the initial width when resized for the first time.
|
|||
minWidth = 0, |
|||
//holds the offset of the resize handle.
|
|||
handleOffset = 0 |
|||
; |
|||
|
|||
/** |
|||
* Helper: sets the element width/height and updates left coordinate if neccessary. |
|||
* |
|||
* @param {Event} event DOM mousemove event object. |
|||
* @param {Node} element The element being moved. |
|||
* @param {Boolean} pinned A flag indicating if the element being resized is pinned to the screen. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function resizeElement(event, element, pageRelative) { |
|||
|
|||
//calculate offsets from 0,0
|
|||
var current = element; |
|||
var offsetLeft = 0; |
|||
var offsetTop = 0; |
|||
do { |
|||
offsetLeft += current.offsetLeft; |
|||
offsetTop += current.offsetTop; |
|||
} while (current = current.offsetParent); |
|||
|
|||
// determine X,Y coordinates.
|
|||
var X, Y; |
|||
if (pageRelative === true) { |
|||
X = event.pageX; |
|||
Y = event.pageY; |
|||
} else { |
|||
X = event.clientX; |
|||
Y = event.clientY; |
|||
} |
|||
// rtl handling
|
|||
var isRTL = isRightToLeft(); |
|||
if (isRTL) { |
|||
// reverse X
|
|||
X = document.body.offsetWidth - X; |
|||
// if has a starting left, calculate offsetRight
|
|||
if (!isNaN(startingLeft)) { |
|||
offsetLeft = document.body.offsetWidth - offsetLeft - element.offsetWidth; |
|||
} |
|||
} |
|||
|
|||
// set width/height
|
|||
element.style.height = (Y - offsetTop + handleOffset) + 'px'; |
|||
element.style.width = (X - offsetLeft + handleOffset) + 'px'; |
|||
|
|||
// if the element being resized has a starting left, maintain it.
|
|||
// the dialog is centered, divide by half the offset to maintain the margins.
|
|||
if (!isNaN(startingLeft)) { |
|||
var diff = Math.abs(element.offsetWidth - startingWidth) * 0.5; |
|||
if (isRTL) { |
|||
//negate the diff, why?
|
|||
//when growing it should decrease left
|
|||
//when shrinking it should increase left
|
|||
diff *= -1; |
|||
} |
|||
if (element.offsetWidth > startingWidth) { |
|||
//growing
|
|||
element.style.left = (startingLeft + diff) + 'px'; |
|||
} else if (element.offsetWidth >= minWidth) { |
|||
//shrinking
|
|||
element.style.left = (startingLeft - diff) + 'px'; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Triggers the start of a resize event, attached to the resize handle element mouse down event. |
|||
* Adds no-selection class to the body, disabling selection while moving. |
|||
* |
|||
* @param {Event} event DOM event object. |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {Boolean} false |
|||
*/ |
|||
function beginResize(event, instance) { |
|||
if (!instance.isMaximized()) { |
|||
var eventSrc; |
|||
if (event.type === 'touchstart') { |
|||
event.preventDefault(); |
|||
eventSrc = event.targetTouches[0]; |
|||
} else if (event.button === 0) { |
|||
eventSrc = event; |
|||
} |
|||
if (eventSrc) { |
|||
// allow custom `onresize` method
|
|||
dispatchEvent('onresize', instance); |
|||
|
|||
resizable = instance; |
|||
handleOffset = instance.elements.resizeHandle.offsetHeight / 2; |
|||
var element = instance.elements.dialog; |
|||
addClass(element, classes.capture); |
|||
startingLeft = parseInt(element.style.left, 10); |
|||
element.style.height = element.offsetHeight + 'px'; |
|||
element.style.minHeight = instance.elements.header.offsetHeight + instance.elements.footer.offsetHeight + 'px'; |
|||
element.style.width = (startingWidth = element.offsetWidth) + 'px'; |
|||
|
|||
if (element.style.maxWidth !== 'none') { |
|||
element.style.minWidth = (minWidth = element.offsetWidth) + 'px'; |
|||
} |
|||
element.style.maxWidth = 'none'; |
|||
addClass(document.body, classes.noSelection); |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* The actual resize handler, attached to document.body mousemove event. |
|||
* |
|||
* @param {Event} event DOM event object. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function resize(event) { |
|||
if (resizable) { |
|||
var eventSrc; |
|||
if (event.type === 'touchmove') { |
|||
event.preventDefault(); |
|||
eventSrc = event.targetTouches[0]; |
|||
} else if (event.button === 0) { |
|||
eventSrc = event; |
|||
} |
|||
if (eventSrc) { |
|||
resizeElement(eventSrc, resizable.elements.dialog, !resizable.get('modal') && !resizable.get('pinned')); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Triggers the end of a resize event, attached to document.body mouseup event. |
|||
* Removes no-selection class from document.body, allowing selection. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function endResize() { |
|||
if (resizable) { |
|||
var instance = resizable; |
|||
resizable = null; |
|||
removeClass(document.body, classes.noSelection); |
|||
removeClass(instance.elements.dialog, classes.capture); |
|||
cancelClick = true; |
|||
// allow custom `onresized` method
|
|||
dispatchEvent('onresized', instance); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Resets any changes made by resizing the element to its original state. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function resetResize(instance) { |
|||
resizable = null; |
|||
var element = instance.elements.dialog; |
|||
if (element.style.maxWidth === 'none') { |
|||
//clear inline styles.
|
|||
element.style.maxWidth = element.style.minWidth = element.style.width = element.style.height = element.style.minHeight = element.style.left = ''; |
|||
//reset variables.
|
|||
startingLeft = Number.Nan; |
|||
startingWidth = minWidth = handleOffset = 0; |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Updates the dialog move behavior. |
|||
* |
|||
* @param {Object} instance The dilog instance. |
|||
* @param {Boolean} on True to add the behavior, removes it otherwise. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function updateResizable(instance) { |
|||
if (instance.get('resizable')) { |
|||
// add class
|
|||
addClass(instance.elements.root, classes.resizable); |
|||
if (instance.isOpen()) { |
|||
bindResizableEvents(instance); |
|||
} |
|||
} else { |
|||
//reset
|
|||
resetResize(instance); |
|||
// remove class
|
|||
removeClass(instance.elements.root, classes.resizable); |
|||
if (instance.isOpen()) { |
|||
unbindResizableEvents(instance); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Reset move/resize on window resize. |
|||
* |
|||
* @param {Event} event window resize event object. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function windowResize(/*event*/) { |
|||
for (var x = 0; x < openDialogs.length; x += 1) { |
|||
var instance = openDialogs[x]; |
|||
if (instance.get('autoReset')) { |
|||
resetMove(instance); |
|||
resetResize(instance); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,65 @@ |
|||
/** |
|||
* Transition in transitionend event handler. |
|||
* |
|||
* @param {Event} TransitionEnd event object. |
|||
* @param {Object} The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function handleTransitionInEvent(event, instance) { |
|||
// clear the timer
|
|||
clearTimeout(instance.__internal.timerIn); |
|||
|
|||
// once transition is complete, set focus
|
|||
setFocus(instance); |
|||
|
|||
//restore scroll to prevent document jump
|
|||
restoreScrollPosition(); |
|||
|
|||
// allow handling key up after transition ended.
|
|||
cancelKeyup = false; |
|||
|
|||
// allow custom `onfocus` method
|
|||
dispatchEvent('onfocus', instance); |
|||
|
|||
// unbind the event
|
|||
off(instance.elements.dialog, transition.type, instance.__internal.transitionInHandler); |
|||
|
|||
removeClass(instance.elements.root, classes.animationIn); |
|||
} |
|||
|
|||
/** |
|||
* Transition out transitionend event handler. |
|||
* |
|||
* @param {Event} TransitionEnd event object. |
|||
* @param {Object} The dilog instance. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function handleTransitionOutEvent(event, instance) { |
|||
// clear the timer
|
|||
clearTimeout(instance.__internal.timerOut); |
|||
// unbind the event
|
|||
off(instance.elements.dialog, transition.type, instance.__internal.transitionOutHandler); |
|||
|
|||
// reset move updates
|
|||
resetMove(instance); |
|||
// reset resize updates
|
|||
resetResize(instance); |
|||
|
|||
// restore if maximized
|
|||
if (instance.isMaximized() && !instance.get('startMaximized')) { |
|||
restore(instance); |
|||
} |
|||
|
|||
// return focus to the last active element
|
|||
if (alertify.defaults.maintainFocus && instance.__internal.activeElement) { |
|||
instance.__internal.activeElement.focus(); |
|||
instance.__internal.activeElement = null; |
|||
} |
|||
|
|||
//destory the instance
|
|||
if (typeof instance.__internal.destroy === 'function') { |
|||
instance.__internal.destroy.apply(instance); |
|||
} |
|||
} |
@ -0,0 +1,131 @@ |
|||
/** |
|||
* Use a closure to return proper event listener method. Try to use |
|||
* `addEventListener` by default but fallback to `attachEvent` for |
|||
* unsupported browser. The closure simply ensures that the test doesn't |
|||
* happen every time the method is called. |
|||
* |
|||
* @param {Node} el Node element |
|||
* @param {String} event Event type |
|||
* @param {Function} fn Callback of event |
|||
* @return {Function} |
|||
*/ |
|||
var on = (function () { |
|||
if (document.addEventListener) { |
|||
return function (el, event, fn, useCapture) { |
|||
el.addEventListener(event, fn, useCapture === true); |
|||
}; |
|||
} else if (document.attachEvent) { |
|||
return function (el, event, fn) { |
|||
el.attachEvent('on' + event, fn); |
|||
}; |
|||
} |
|||
}()); |
|||
|
|||
/** |
|||
* Use a closure to return proper event listener method. Try to use |
|||
* `removeEventListener` by default but fallback to `detachEvent` for |
|||
* unsupported browser. The closure simply ensures that the test doesn't |
|||
* happen every time the method is called. |
|||
* |
|||
* @param {Node} el Node element |
|||
* @param {String} event Event type |
|||
* @param {Function} fn Callback of event |
|||
* @return {Function} |
|||
*/ |
|||
var off = (function () { |
|||
if (document.removeEventListener) { |
|||
return function (el, event, fn, useCapture) { |
|||
el.removeEventListener(event, fn, useCapture === true); |
|||
}; |
|||
} else if (document.detachEvent) { |
|||
return function (el, event, fn) { |
|||
el.detachEvent('on' + event, fn); |
|||
}; |
|||
} |
|||
}()); |
|||
|
|||
/** |
|||
* Prevent default event from firing |
|||
* |
|||
* @param {Event} event Event object |
|||
* @return {undefined} |
|||
|
|||
function prevent ( event ) { |
|||
if ( event ) { |
|||
if ( event.preventDefault ) { |
|||
event.preventDefault(); |
|||
} else { |
|||
event.returnValue = false; |
|||
} |
|||
} |
|||
} |
|||
*/ |
|||
var transition = (function () { |
|||
var t, type; |
|||
var supported = false; |
|||
var transitions = { |
|||
'animation' : 'animationend', |
|||
'OAnimation' : 'oAnimationEnd oanimationend', |
|||
'msAnimation' : 'MSAnimationEnd', |
|||
'MozAnimation' : 'animationend', |
|||
'WebkitAnimation' : 'webkitAnimationEnd' |
|||
}; |
|||
|
|||
for (t in transitions) { |
|||
if (document.documentElement.style[t] !== undefined) { |
|||
type = transitions[t]; |
|||
supported = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return { |
|||
type: type, |
|||
supported: supported |
|||
}; |
|||
}()); |
|||
|
|||
/** |
|||
* Creates event handler delegate that sends the instance as last argument. |
|||
* |
|||
* @return {Function} a function wrapper which sends the instance as last argument. |
|||
*/ |
|||
function delegate(context, method) { |
|||
return function () { |
|||
if (arguments.length > 0) { |
|||
var args = []; |
|||
for (var x = 0; x < arguments.length; x += 1) { |
|||
args.push(arguments[x]); |
|||
} |
|||
args.push(context); |
|||
return method.apply(context, args); |
|||
} |
|||
return method.apply(context, [null, context]); |
|||
}; |
|||
} |
|||
/** |
|||
* Helper for creating a dialog close event. |
|||
* |
|||
* @return {object} |
|||
*/ |
|||
function createCloseEvent(index, button) { |
|||
return { |
|||
index: index, |
|||
button: button, |
|||
cancel: false |
|||
}; |
|||
} |
|||
/** |
|||
* Helper for dispatching events. |
|||
* |
|||
* @param {string} evenType The type of the event to disptach. |
|||
* @param {object} instance The dialog instance disptaching the event. |
|||
* |
|||
* @return {any} The result of the invoked function. |
|||
*/ |
|||
function dispatchEvent(eventType, instance) { |
|||
if ( typeof instance.get(eventType) === 'function' ) { |
|||
return instance.get(eventType).call(instance); |
|||
} |
|||
} |
|||
|
@ -0,0 +1,217 @@ |
|||
( function ( window ) { |
|||
'use strict'; |
|||
var NOT_DISABLED_NOT_RESET = ':not(:disabled):not(.ajs-reset)'; |
|||
/** |
|||
* Keys enum |
|||
* @type {Object} |
|||
*/ |
|||
var keys = { |
|||
ENTER: 13, |
|||
ESC: 27, |
|||
F1: 112, |
|||
F12: 123, |
|||
LEFT: 37, |
|||
RIGHT: 39, |
|||
TAB: 9 |
|||
}; |
|||
/** |
|||
* Default options |
|||
* @type {Object} |
|||
*/ |
|||
var defaults = { |
|||
autoReset:true, |
|||
basic:false, |
|||
closable:true, |
|||
closableByDimmer:true, |
|||
invokeOnCloseOff:false, |
|||
frameless:false, |
|||
defaultFocusOff:false, |
|||
maintainFocus:true, //global default not per instance, applies to all dialogs
|
|||
maximizable:true, |
|||
modal:true, |
|||
movable:true, |
|||
moveBounded:false, |
|||
overflow:true, |
|||
padding: true, |
|||
pinnable:true, |
|||
pinned:true, |
|||
preventBodyShift:false, //global default not per instance, applies to all dialogs
|
|||
resizable:true, |
|||
startMaximized:false, |
|||
transition:'pulse', |
|||
tabbable:['button', '[href]', 'input', 'select', 'textarea', '[tabindex]:not([tabindex^="-"])'+NOT_DISABLED_NOT_RESET].join(NOT_DISABLED_NOT_RESET+','),//global
|
|||
notifier:{ |
|||
delay:5, |
|||
position:'bottom-right', |
|||
closeButton:false, |
|||
classes: { |
|||
base: 'alertify-notifier', |
|||
prefix:'ajs-', |
|||
message: 'ajs-message', |
|||
top: 'ajs-top', |
|||
right: 'ajs-right', |
|||
bottom: 'ajs-bottom', |
|||
left: 'ajs-left', |
|||
center: 'ajs-center', |
|||
visible: 'ajs-visible', |
|||
hidden: 'ajs-hidden', |
|||
close: 'ajs-close' |
|||
} |
|||
}, |
|||
glossary:{ |
|||
title:'AlertifyJS', |
|||
ok: 'OK', |
|||
cancel: 'Cancel', |
|||
acccpt: 'Accept', |
|||
deny: 'Deny', |
|||
confirm: 'Confirm', |
|||
decline: 'Decline', |
|||
close: 'Close', |
|||
maximize: 'Maximize', |
|||
restore: 'Restore', |
|||
}, |
|||
theme:{ |
|||
input:'ajs-input', |
|||
ok:'ajs-ok', |
|||
cancel:'ajs-cancel', |
|||
}, |
|||
hooks:{ |
|||
preinit:function(){}, |
|||
postinit:function(){} |
|||
} |
|||
}; |
|||
|
|||
//holds open dialogs instances
|
|||
var openDialogs = []; |
|||
|
|||
/** |
|||
* [Helper] Adds the specified class(es) to the element. |
|||
* |
|||
* @element {node} The element |
|||
* @className {string} One or more space-separated classes to be added to the class attribute of the element. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function addClass(element,classNames){ |
|||
element.className += ' ' + classNames; |
|||
} |
|||
|
|||
/** |
|||
* [Helper] Removes the specified class(es) from the element. |
|||
* |
|||
* @element {node} The element |
|||
* @className {string} One or more space-separated classes to be removed from the class attribute of the element. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function removeClass(element, classNames) { |
|||
var original = element.className.split(' '); |
|||
var toBeRemoved = classNames.split(' '); |
|||
for (var x = 0; x < toBeRemoved.length; x += 1) { |
|||
var index = original.indexOf(toBeRemoved[x]); |
|||
if (index > -1){ |
|||
original.splice(index,1); |
|||
} |
|||
} |
|||
element.className = original.join(' '); |
|||
} |
|||
|
|||
/** |
|||
* [Helper] Checks if the document is RTL |
|||
* |
|||
* @return {Boolean} True if the document is RTL, false otherwise. |
|||
*/ |
|||
function isRightToLeft(){ |
|||
return window.getComputedStyle(document.body).direction === 'rtl'; |
|||
} |
|||
/** |
|||
* [Helper] Get the document current scrollTop |
|||
* |
|||
* @return {Number} current document scrollTop value |
|||
*/ |
|||
function getScrollTop(){ |
|||
return ((document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop); |
|||
} |
|||
|
|||
/** |
|||
* [Helper] Get the document current scrollLeft |
|||
* |
|||
* @return {Number} current document scrollLeft value |
|||
*/ |
|||
function getScrollLeft(){ |
|||
return ((document.documentElement && document.documentElement.scrollLeft) || document.body.scrollLeft); |
|||
} |
|||
|
|||
/** |
|||
* Helper: clear contents |
|||
* |
|||
*/ |
|||
function clearContents(element){ |
|||
while (element.lastChild) { |
|||
element.removeChild(element.lastChild); |
|||
} |
|||
} |
|||
/** |
|||
* Extends a given prototype by merging properties from base into sub. |
|||
* |
|||
* @sub {Object} sub The prototype being overwritten. |
|||
* @base {Object} base The prototype being written. |
|||
* |
|||
* @return {Object} The extended prototype. |
|||
*/ |
|||
function copy(src) { |
|||
if(null === src){ |
|||
return src; |
|||
} |
|||
var cpy; |
|||
if(Array.isArray(src)){ |
|||
cpy = []; |
|||
for(var x=0;x<src.length;x+=1){ |
|||
cpy.push(copy(src[x])); |
|||
} |
|||
return cpy; |
|||
} |
|||
|
|||
if(src instanceof Date){ |
|||
return new Date(src.getTime()); |
|||
} |
|||
|
|||
if(src instanceof RegExp){ |
|||
cpy = new RegExp(src.source); |
|||
cpy.global = src.global; |
|||
cpy.ignoreCase = src.ignoreCase; |
|||
cpy.multiline = src.multiline; |
|||
cpy.lastIndex = src.lastIndex; |
|||
return cpy; |
|||
} |
|||
|
|||
if(typeof src === 'object'){ |
|||
cpy = {}; |
|||
// copy dialog pototype over definition.
|
|||
for (var prop in src) { |
|||
if (src.hasOwnProperty(prop)) { |
|||
cpy[prop] = copy(src[prop]); |
|||
} |
|||
} |
|||
return cpy; |
|||
} |
|||
return src; |
|||
} |
|||
/** |
|||
* Helper: destruct the dialog |
|||
* |
|||
*/ |
|||
function destruct(instance, initialize){ |
|||
if(instance.elements){ |
|||
//delete the dom and it's references.
|
|||
var root = instance.elements.root; |
|||
root.parentNode.removeChild(root); |
|||
delete instance.elements; |
|||
//copy back initial settings.
|
|||
instance.settings = copy(instance.__settings); |
|||
//re-reference init function.
|
|||
instance.__init = initialize; |
|||
//delete __internal variable to allow re-initialization.
|
|||
delete instance.__internal; |
|||
} |
|||
} |
@ -0,0 +1,322 @@ |
|||
var notifier = (function () { |
|||
var reflow, |
|||
element, |
|||
openInstances = [], |
|||
classes = defaults.notifier.classes; |
|||
/** |
|||
* Helper: initializes the notifier instance |
|||
* |
|||
*/ |
|||
function initialize(instance) { |
|||
|
|||
if (!instance.__internal) { |
|||
instance.__internal = { |
|||
position: alertify.defaults.notifier.position, |
|||
delay: alertify.defaults.notifier.delay, |
|||
}; |
|||
|
|||
element = document.createElement('DIV'); |
|||
|
|||
updatePosition(instance); |
|||
} |
|||
|
|||
//add to DOM tree.
|
|||
if (element.parentNode !== document.body) { |
|||
document.body.appendChild(element); |
|||
} |
|||
} |
|||
|
|||
function pushInstance(instance) { |
|||
instance.__internal.pushed = true; |
|||
openInstances.push(instance); |
|||
} |
|||
function popInstance(instance) { |
|||
openInstances.splice(openInstances.indexOf(instance), 1); |
|||
instance.__internal.pushed = false; |
|||
} |
|||
/** |
|||
* Helper: update the notifier instance position |
|||
* |
|||
*/ |
|||
function updatePosition(instance) { |
|||
element.className = classes.base; |
|||
switch (instance.__internal.position) { |
|||
case 'top-right': |
|||
addClass(element, classes.top + ' ' + classes.right); |
|||
break; |
|||
case 'top-left': |
|||
addClass(element, classes.top + ' ' + classes.left); |
|||
break; |
|||
case 'top-center': |
|||
addClass(element, classes.top + ' ' + classes.center); |
|||
break; |
|||
case 'bottom-left': |
|||
addClass(element, classes.bottom + ' ' + classes.left); |
|||
break; |
|||
case 'bottom-center': |
|||
addClass(element, classes.bottom + ' ' + classes.center); |
|||
break; |
|||
|
|||
default: |
|||
case 'bottom-right': |
|||
addClass(element, classes.bottom + ' ' + classes.right); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* creates a new notification message |
|||
* |
|||
* @param {DOMElement} message The notifier message element |
|||
* @param {Number} wait Time (in ms) to wait before the message is dismissed, a value of 0 means keep open till clicked. |
|||
* @param {Function} callback A callback function to be invoked when the message is dismissed. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
function create(div, callback) { |
|||
|
|||
function clickDelegate(event, instance) { |
|||
if(!instance.__internal.closeButton || event.target.getAttribute('data-close') === 'true'){ |
|||
instance.dismiss(true); |
|||
} |
|||
} |
|||
|
|||
function transitionDone(event, instance) { |
|||
// unbind event
|
|||
off(instance.element, transition.type, transitionDone); |
|||
// remove the message
|
|||
element.removeChild(instance.element); |
|||
} |
|||
|
|||
function initialize(instance) { |
|||
if (!instance.__internal) { |
|||
instance.__internal = { |
|||
pushed: false, |
|||
delay : undefined, |
|||
timer: undefined, |
|||
clickHandler: undefined, |
|||
transitionEndHandler: undefined, |
|||
transitionTimeout: undefined |
|||
}; |
|||
instance.__internal.clickHandler = delegate(instance, clickDelegate); |
|||
instance.__internal.transitionEndHandler = delegate(instance, transitionDone); |
|||
} |
|||
return instance; |
|||
} |
|||
function clearTimers(instance) { |
|||
clearTimeout(instance.__internal.timer); |
|||
clearTimeout(instance.__internal.transitionTimeout); |
|||
} |
|||
return initialize({ |
|||
/* notification DOM element*/ |
|||
element: div, |
|||
/* |
|||
* Pushes a notification message |
|||
* @param {string or DOMElement} content The notification message content |
|||
* @param {Number} wait The time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked. |
|||
* |
|||
*/ |
|||
push: function (_content, _wait) { |
|||
if (!this.__internal.pushed) { |
|||
|
|||
pushInstance(this); |
|||
clearTimers(this); |
|||
|
|||
var content, wait; |
|||
switch (arguments.length) { |
|||
case 0: |
|||
wait = this.__internal.delay; |
|||
break; |
|||
case 1: |
|||
if (typeof (_content) === 'number') { |
|||
wait = _content; |
|||
} else { |
|||
content = _content; |
|||
wait = this.__internal.delay; |
|||
} |
|||
break; |
|||
case 2: |
|||
content = _content; |
|||
wait = _wait; |
|||
break; |
|||
} |
|||
this.__internal.closeButton = alertify.defaults.notifier.closeButton; |
|||
// set contents
|
|||
if (typeof content !== 'undefined') { |
|||
this.setContent(content); |
|||
} |
|||
// append or insert
|
|||
if (notifier.__internal.position.indexOf('top') < 0) { |
|||
element.appendChild(this.element); |
|||
} else { |
|||
element.insertBefore(this.element, element.firstChild); |
|||
} |
|||
reflow = this.element.offsetWidth; |
|||
addClass(this.element, classes.visible); |
|||
// attach click event
|
|||
on(this.element, 'click', this.__internal.clickHandler); |
|||
return this.delay(wait); |
|||
} |
|||
return this; |
|||
}, |
|||
/* |
|||
* {Function} callback function to be invoked before dismissing the notification message. |
|||
* Remarks: A return value === 'false' will cancel the dismissal |
|||
* |
|||
*/ |
|||
ondismiss: function () { }, |
|||
/* |
|||
* {Function} callback function to be invoked when the message is dismissed. |
|||
* |
|||
*/ |
|||
callback: callback, |
|||
/* |
|||
* Dismisses the notification message |
|||
* @param {Boolean} clicked A flag indicating if the dismissal was caused by a click. |
|||
* |
|||
*/ |
|||
dismiss: function (clicked) { |
|||
if (this.__internal.pushed) { |
|||
clearTimers(this); |
|||
if (!(typeof this.ondismiss === 'function' && this.ondismiss.call(this) === false)) { |
|||
//detach click event
|
|||
off(this.element, 'click', this.__internal.clickHandler); |
|||
// ensure element exists
|
|||
if (typeof this.element !== 'undefined' && this.element.parentNode === element) { |
|||
//transition end or fallback
|
|||
this.__internal.transitionTimeout = setTimeout(this.__internal.transitionEndHandler, transition.supported ? 1000 : 100); |
|||
removeClass(this.element, classes.visible); |
|||
|
|||
// custom callback on dismiss
|
|||
if (typeof this.callback === 'function') { |
|||
this.callback.call(this, clicked); |
|||
} |
|||
} |
|||
popInstance(this); |
|||
} |
|||
} |
|||
return this; |
|||
}, |
|||
/* |
|||
* Delays the notification message dismissal |
|||
* @param {Number} wait The time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked. |
|||
* |
|||
*/ |
|||
delay: function (wait) { |
|||
clearTimers(this); |
|||
this.__internal.delay = typeof wait !== 'undefined' && !isNaN(+wait) ? +wait : notifier.__internal.delay; |
|||
if (this.__internal.delay > 0) { |
|||
var self = this; |
|||
this.__internal.timer = setTimeout(function () { self.dismiss(); }, this.__internal.delay * 1000); |
|||
} |
|||
return this; |
|||
}, |
|||
/* |
|||
* Sets the notification message contents |
|||
* @param {string or DOMElement} content The notification message content |
|||
* |
|||
*/ |
|||
setContent: function (content) { |
|||
if (typeof content === 'string') { |
|||
clearContents(this.element); |
|||
this.element.innerHTML = content; |
|||
} else if (content instanceof window.HTMLElement && this.element.firstChild !== content) { |
|||
clearContents(this.element); |
|||
this.element.appendChild(content); |
|||
} |
|||
if(this.__internal.closeButton){ |
|||
var close = document.createElement('span'); |
|||
addClass(close, classes.close); |
|||
close.setAttribute('data-close', true); |
|||
this.element.appendChild(close); |
|||
} |
|||
return this; |
|||
}, |
|||
/* |
|||
* Dismisses all open notifications except this. |
|||
* |
|||
*/ |
|||
dismissOthers: function () { |
|||
notifier.dismissAll(this); |
|||
return this; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
//notifier api
|
|||
return { |
|||
/** |
|||
* Gets or Sets notifier settings. |
|||
* |
|||
* @param {string} key The setting name |
|||
* @param {Variant} value The setting value. |
|||
* |
|||
* @return {Object} if the called as a setter, return the notifier instance. |
|||
*/ |
|||
setting: function (key, value) { |
|||
//ensure init
|
|||
initialize(this); |
|||
|
|||
if (typeof value === 'undefined') { |
|||
//get
|
|||
return this.__internal[key]; |
|||
} else { |
|||
//set
|
|||
switch (key) { |
|||
case 'position': |
|||
this.__internal.position = value; |
|||
updatePosition(this); |
|||
break; |
|||
case 'delay': |
|||
this.__internal.delay = value; |
|||
break; |
|||
} |
|||
} |
|||
return this; |
|||
}, |
|||
/** |
|||
* [Alias] Sets dialog settings/options |
|||
*/ |
|||
set:function(key,value){ |
|||
this.setting(key,value); |
|||
return this; |
|||
}, |
|||
/** |
|||
* [Alias] Gets dialog settings/options |
|||
*/ |
|||
get:function(key){ |
|||
return this.setting(key); |
|||
}, |
|||
/** |
|||
* Creates a new notification message |
|||
* |
|||
* @param {string} type The type of notification message (simply a CSS class name 'ajs-{type}' to be added). |
|||
* @param {Function} callback A callback function to be invoked when the message is dismissed. |
|||
* |
|||
* @return {undefined} |
|||
*/ |
|||
create: function (type, callback) { |
|||
//ensure notifier init
|
|||
initialize(this); |
|||
//create new notification message
|
|||
var div = document.createElement('div'); |
|||
div.className = classes.message + ((typeof type === 'string' && type !== '') ? ' ' + classes.prefix + type : ''); |
|||
return create(div, callback); |
|||
}, |
|||
/** |
|||
* Dismisses all open notifications. |
|||
* |
|||
* @param {Object} excpet [optional] The notification object to exclude from dismissal. |
|||
* |
|||
*/ |
|||
dismissAll: function (except) { |
|||
var clone = openInstances.slice(0); |
|||
for (var x = 0; x < clone.length; x += 1) { |
|||
var instance = clone[x]; |
|||
if (except === undefined || except !== instance) { |
|||
instance.dismiss(); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
})(); |
@ -0,0 +1,14 @@ |
|||
// CommonJS
|
|||
if ( typeof module === 'object' && typeof module.exports === 'object' ) { |
|||
module.exports = alertify; |
|||
// AMD
|
|||
} else if ( typeof define === 'function' && define.amd) { |
|||
define( [], function () { |
|||
return alertify; |
|||
} ); |
|||
// window
|
|||
} else if ( !window.alertify ) { |
|||
window.alertify = alertify; |
|||
} |
|||
|
|||
} ( typeof window !== 'undefined' ? window : this ) ); |
@ -0,0 +1,176 @@ |
|||
/** |
|||
* Prompt dialog object |
|||
* |
|||
* invoked by: |
|||
* alertify.prompt(message); |
|||
* alertify.prompt(message, value); |
|||
* alertify.prompt(message, value, onok); |
|||
* alertify.prompt(message, value, onok, oncancel); |
|||
* alertify.prompt(title, message, value, onok, oncancel); |
|||
*/ |
|||
alertify.dialog('prompt', function () { |
|||
var input = document.createElement('INPUT'); |
|||
var p = document.createElement('P'); |
|||
return { |
|||
main: function (_title, _message, _value, _onok, _oncancel) { |
|||
var title, message, value, onok, oncancel; |
|||
switch (arguments.length) { |
|||
case 1: |
|||
message = _title; |
|||
break; |
|||
case 2: |
|||
message = _title; |
|||
value = _message; |
|||
break; |
|||
case 3: |
|||
message = _title; |
|||
value = _message; |
|||
onok = _value; |
|||
break; |
|||
case 4: |
|||
message = _title; |
|||
value = _message; |
|||
onok = _value; |
|||
oncancel = _onok; |
|||
break; |
|||
case 5: |
|||
title = _title; |
|||
message = _message; |
|||
value = _value; |
|||
onok = _onok; |
|||
oncancel = _oncancel; |
|||
break; |
|||
} |
|||
this.set('title', title); |
|||
this.set('message', message); |
|||
this.set('value', value); |
|||
this.set('onok', onok); |
|||
this.set('oncancel', oncancel); |
|||
return this; |
|||
}, |
|||
setup: function () { |
|||
return { |
|||
buttons: [ |
|||
{ |
|||
text: alertify.defaults.glossary.ok, |
|||
key: keys.ENTER, |
|||
className: alertify.defaults.theme.ok, |
|||
}, |
|||
{ |
|||
text: alertify.defaults.glossary.cancel, |
|||
key: keys.ESC, |
|||
invokeOnClose: true, |
|||
className: alertify.defaults.theme.cancel, |
|||
} |
|||
], |
|||
focus: { |
|||
element: input, |
|||
select: true |
|||
}, |
|||
options: { |
|||
maximizable: false, |
|||
resizable: false |
|||
} |
|||
}; |
|||
}, |
|||
build: function () { |
|||
input.className = alertify.defaults.theme.input; |
|||
input.setAttribute('type', 'text'); |
|||
input.value = this.get('value'); |
|||
this.elements.content.appendChild(p); |
|||
this.elements.content.appendChild(input); |
|||
}, |
|||
prepare: function () { |
|||
//nothing
|
|||
}, |
|||
setMessage: function (message) { |
|||
if (typeof message === 'string') { |
|||
clearContents(p); |
|||
p.innerHTML = message; |
|||
} else if (message instanceof window.HTMLElement && p.firstChild !== message) { |
|||
clearContents(p); |
|||
p.appendChild(message); |
|||
} |
|||
}, |
|||
settings: { |
|||
message: undefined, |
|||
labels: undefined, |
|||
onok: undefined, |
|||
oncancel: undefined, |
|||
value: '', |
|||
type:'text', |
|||
reverseButtons: undefined, |
|||
}, |
|||
settingUpdated: function (key, oldValue, newValue) { |
|||
switch (key) { |
|||
case 'message': |
|||
this.setMessage(newValue); |
|||
break; |
|||
case 'value': |
|||
input.value = newValue; |
|||
break; |
|||
case 'type': |
|||
switch (newValue) { |
|||
case 'text': |
|||
case 'color': |
|||
case 'date': |
|||
case 'datetime-local': |
|||
case 'email': |
|||
case 'month': |
|||
case 'number': |
|||
case 'password': |
|||
case 'search': |
|||
case 'tel': |
|||
case 'time': |
|||
case 'week': |
|||
input.type = newValue; |
|||
break; |
|||
default: |
|||
input.type = 'text'; |
|||
break; |
|||
} |
|||
break; |
|||
case 'labels': |
|||
if (newValue.ok && this.__internal.buttons[0].element) { |
|||
this.__internal.buttons[0].element.innerHTML = newValue.ok; |
|||
} |
|||
if (newValue.cancel && this.__internal.buttons[1].element) { |
|||
this.__internal.buttons[1].element.innerHTML = newValue.cancel; |
|||
} |
|||
break; |
|||
case 'reverseButtons': |
|||
if (newValue === true) { |
|||
this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element); |
|||
} else { |
|||
this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element); |
|||
} |
|||
break; |
|||
} |
|||
}, |
|||
callback: function (closeEvent) { |
|||
var returnValue; |
|||
switch (closeEvent.index) { |
|||
case 0: |
|||
this.settings.value = input.value; |
|||
if (typeof this.get('onok') === 'function') { |
|||
returnValue = this.get('onok').call(this, closeEvent, this.settings.value); |
|||
if (typeof returnValue !== 'undefined') { |
|||
closeEvent.cancel = !returnValue; |
|||
} |
|||
} |
|||
break; |
|||
case 1: |
|||
if (typeof this.get('oncancel') === 'function') { |
|||
returnValue = this.get('oncancel').call(this, closeEvent); |
|||
if (typeof returnValue !== 'undefined') { |
|||
closeEvent.cancel = !returnValue; |
|||
} |
|||
} |
|||
if(!closeEvent.cancel){ |
|||
input.value = this.settings.value; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
}; |
|||
}); |
@ -0,0 +1,921 @@ |
|||
.alertify { |
|||
.dimmer { |
|||
position: fixed; |
|||
z-index: 1981; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
padding: 0; |
|||
margin: 0; |
|||
background-color: #252525; |
|||
opacity: .5; |
|||
} |
|||
|
|||
.modal { |
|||
position: fixed; |
|||
top: 0; |
|||
right: 0; |
|||
left: 0; |
|||
bottom: 0; |
|||
padding: 0; |
|||
overflow-y: auto; |
|||
z-index: 1981; |
|||
} |
|||
|
|||
.dialog { |
|||
position: relative; |
|||
margin: 5% auto; |
|||
min-height: 110px; |
|||
max-width: 500px; |
|||
padding: 24px 24px 0 24px; |
|||
outline: 0; |
|||
background-color: #fff; |
|||
|
|||
&.capture:before { |
|||
content: ''; |
|||
position: absolute; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
display: block; |
|||
z-index: 1; |
|||
} |
|||
} |
|||
|
|||
.reset { |
|||
position: absolute !important; |
|||
display: inline !important; |
|||
width: 0 !important; |
|||
height: 0 !important; |
|||
opacity: 0 !important; |
|||
} |
|||
|
|||
.commands { |
|||
position: absolute; |
|||
right: 4px; |
|||
margin: -14px 24px 0 0; |
|||
z-index: 2; |
|||
|
|||
button { |
|||
display: none; |
|||
width: 10px; |
|||
height: 10px; |
|||
margin-left: 10px; |
|||
padding: 10px; |
|||
border: 0; |
|||
background-color: transparent; |
|||
background-repeat: no-repeat; |
|||
background-position: center; |
|||
cursor: pointer; |
|||
|
|||
&.close { |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQYlY2QsQ0EIQwEB9cBAR1CJUaI/gigDnwR6NBL/7/xWLNrZ2b8EwGotVpr7eOitWa1VjugiNB7R1UPrKrWe0dEAHBbXUqxMQbeewDmnHjvyTm7C3zDwAUd9c63YQdUVdu6EAJzzquz7HXvTiklt+H9DQFYaxFjvDqllFyMkbXWvfpXHjJrWFgdBq/hAAAAAElFTkSuQmCC); |
|||
} |
|||
|
|||
&.maximize { |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOUlEQVQYlWP8//8/AzGAhYGBgaG4uBiv6t7eXkYmooxjYGAgWiELsvHYFMCcRX2rSXcjoSBiJDbAAeD+EGu+8BZcAAAAAElFTkSuQmCC); |
|||
} |
|||
} |
|||
//button |
|||
} |
|||
//commands |
|||
.header { |
|||
margin: -24px; |
|||
margin-bottom: 0; |
|||
padding: 16px 24px; |
|||
background-color: #fff; |
|||
} |
|||
|
|||
.body { |
|||
min-height: 56px; |
|||
|
|||
.content { |
|||
padding: 16px 24px 16px 16px; |
|||
} |
|||
} |
|||
|
|||
.footer { |
|||
padding: 4px; |
|||
margin-left: -24px; |
|||
margin-right: -24px; |
|||
min-height: 43px; |
|||
background-color: #fff; |
|||
|
|||
.buttons { |
|||
&.primary { |
|||
text-align: right; |
|||
|
|||
.button { |
|||
margin: 4px; |
|||
} |
|||
} |
|||
|
|||
&.auxiliary { |
|||
float: left; |
|||
clear: none; |
|||
text-align: left; |
|||
|
|||
.button { |
|||
margin: 4px; |
|||
} |
|||
} |
|||
|
|||
.button { |
|||
min-width: 88px; |
|||
min-height: 35px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.handle { |
|||
position: absolute; |
|||
display: none; |
|||
width: 10px; |
|||
height: 10px; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: 1; |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMS8xNEDQYmMAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQ0lEQVQYlaXNMQoAIAxD0dT7H657l0KX3iJuUlBUNOsPPCGJm7VDp6ryeMxMuDsAQH7owW3pyn3RS26iKxERMLN3ugOaAkaL3sWVigAAAABJRU5ErkJggg==); |
|||
transform: scaleX(1) /*rtl:scaleX(-1)*/; |
|||
cursor: se-resize; |
|||
} |
|||
|
|||
// pass overflow control to the content |
|||
&.no-overflow { |
|||
.body { |
|||
.content { |
|||
overflow: hidden !important; |
|||
} |
|||
} |
|||
} |
|||
// pass padding control to the content |
|||
&.no-padding { |
|||
&.maximized { |
|||
.body { |
|||
.content { |
|||
left: 0; |
|||
right: 0; |
|||
padding: 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&:not(.maximized) { |
|||
.body { |
|||
margin-left: -24px; |
|||
margin-right: -24px; |
|||
|
|||
.content { |
|||
padding: 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&.resizable { |
|||
.body { |
|||
.content { |
|||
left: 0; |
|||
right: 0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// has maximize box |
|||
&.maximizable { |
|||
.commands { |
|||
button { |
|||
&.maximize, &.restore { |
|||
display: inline-block; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// has close box |
|||
&.closable { |
|||
.commands { |
|||
button { |
|||
&.close { |
|||
display: inline-block; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// maximizes the dialog |
|||
&.maximized { |
|||
.dialog { |
|||
width: 100% !important; |
|||
height: 100% !important; |
|||
max-width: none !important; |
|||
margin: 0 auto !important; |
|||
top: 0 !important; |
|||
left: 0 !important; |
|||
} |
|||
|
|||
&.modeless .modal { |
|||
position: fixed !important; |
|||
min-height: 100% !important; |
|||
max-height: none !important; |
|||
margin: 0 !important; |
|||
} |
|||
|
|||
.commands { |
|||
button { |
|||
&.maximize { |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAASklEQVQYlZWQ0QkAMQhDtXRincOZX78KVtrDCwgqJNEoIB3MPLj7lRUROlpyVXGzby6zWuY+kz6tj5sBMTMAyVV3/595RbOh3cAXsww1raeiOcoAAAAASUVORK5CYII=); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// resizable dialog |
|||
&.resizable, &.maximized { |
|||
|
|||
.dialog { |
|||
padding: 0; |
|||
} |
|||
|
|||
.commands { |
|||
margin: 14px 24px 0 0; |
|||
} |
|||
|
|||
.header { |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
margin: 0; |
|||
padding: 16px 24px; |
|||
} |
|||
|
|||
.body { |
|||
min-height: 224px; |
|||
display: inline-block; |
|||
|
|||
.content { |
|||
position: absolute; |
|||
top: 50px; |
|||
right: 24px; |
|||
bottom: 50px; |
|||
left: 24px; |
|||
overflow: auto; |
|||
} |
|||
} |
|||
|
|||
.footer { |
|||
position: absolute; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
margin: 0; |
|||
} |
|||
} |
|||
|
|||
&.resizable:not(.maximized) { |
|||
.dialog { |
|||
//max-width + none resizable padding. |
|||
min-width: 548px; |
|||
} |
|||
|
|||
.handle { |
|||
display: block; |
|||
} |
|||
} |
|||
// makes the dialog movable |
|||
&.movable:not(.maximized) { |
|||
|
|||
.header { |
|||
cursor: move; |
|||
} |
|||
} |
|||
// makes the dilog modeless (non-modal) |
|||
&.modeless { |
|||
|
|||
.dimmer, .reset { |
|||
display: none; |
|||
} |
|||
|
|||
.modal { |
|||
overflow: visible; |
|||
max-width: none; |
|||
max-height: 0; |
|||
} |
|||
// has pin box |
|||
&.pinnable { |
|||
.commands { |
|||
button { |
|||
&.pin { |
|||
display: inline-block; |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQklEQVQYlcWPMQ4AIAwCqU9u38GbcbHRWN1MvKQDhQFMEpKImGJA0gCgnYw0V0rwxseg5erT4oSkQVI5d9f+e9+xA0NbLpWfitPXAAAAAElFTkSuQmCC); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
&.unpinned { |
|||
.modal { |
|||
position: absolute; |
|||
} |
|||
|
|||
.commands { |
|||
button { |
|||
&.pin { |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAO0lEQVQYlWP8//8/AzGAiShV6AqLi4txGs+CLoBLMYbC3t5eRmyaWfBZhwwYkX2NTxPRvibKjRhW4wMAhxkYGbLu3pEAAAAASUVORK5CYII=); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
&:not(.unpinned) { |
|||
.body { |
|||
max-height: 500px; |
|||
overflow: auto; |
|||
} |
|||
} |
|||
} |
|||
//basic |
|||
&.basic { |
|||
.header{ |
|||
opacity: 0; |
|||
} |
|||
.footer { |
|||
visibility:hidden; |
|||
} |
|||
} |
|||
//frameless |
|||
&.frameless { |
|||
.header{ |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
min-height:60px; |
|||
margin: 0; |
|||
padding:0; |
|||
opacity:0; |
|||
z-index: 1; |
|||
} |
|||
.footer{ |
|||
display:none; |
|||
} |
|||
.body { |
|||
.content { |
|||
position:absolute; |
|||
top:0; |
|||
right:0; |
|||
bottom:0; |
|||
left:0; |
|||
} |
|||
} |
|||
&:not(.resizable){ |
|||
.dialog{ |
|||
padding-top:0; |
|||
.commands{ |
|||
margin-top:0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
//helpers |
|||
//hides body overflow |
|||
.no-overflow { |
|||
overflow: hidden !important; |
|||
outline: none; |
|||
|
|||
&.fixed { |
|||
position: fixed; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
overflow-y: scroll!important; |
|||
} |
|||
} |
|||
//disables selection |
|||
.no-selection, .no-selection * { |
|||
user-select: none; |
|||
} |
|||
|
|||
@media screen and (max-width: 568px) { |
|||
.alertify { |
|||
.dialog { |
|||
min-width: 150px; |
|||
} |
|||
|
|||
&:not(.maximized) { |
|||
.modal { |
|||
padding: 0 5%; |
|||
} |
|||
|
|||
&.resizable { |
|||
.dialog { |
|||
min-width: initial; |
|||
min-width: auto /*IE fallback*/; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
//fix FF missing outline |
|||
@-moz-document url-prefix() { |
|||
.alertify { |
|||
button:focus{ |
|||
outline: 1px dotted #3593D2; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// transition |
|||
.alertify { |
|||
// setup |
|||
.dimmer, .modal { |
|||
transform: translate3d(0, 0, 0); |
|||
transition-property: opacity, visibility; |
|||
transition-timing-function: linear; |
|||
transition-duration: 250ms; |
|||
} |
|||
|
|||
&.hidden { |
|||
.dimmer, .modal { |
|||
visibility: hidden; |
|||
opacity: 0; |
|||
} |
|||
} |
|||
//in |
|||
&.in:not(.hidden) { |
|||
.dialog { |
|||
animation-duration: 500ms; |
|||
} |
|||
} |
|||
//out |
|||
&.out.hidden { |
|||
.dialog { |
|||
animation-duration: 250ms; |
|||
} |
|||
} |
|||
//helper animation |
|||
.dialog.shake { |
|||
animation-name: ajs-shake; |
|||
animation-duration: .1s; |
|||
animation-fill-mode: both; |
|||
} |
|||
|
|||
@keyframes ajs-shake { |
|||
0%, 100% { |
|||
transform: translate3d(0, 0, 0); |
|||
} |
|||
|
|||
10%, 30%, 50%, 70%, 90% { |
|||
transform: translate3d(-10px, 0, 0); |
|||
} |
|||
|
|||
20%, 40%, 60%, 80% { |
|||
transform: translate3d(10px, 0, 0); |
|||
} |
|||
} |
|||
// slide |
|||
&.slide { |
|||
//in |
|||
&.in:not(.hidden) { |
|||
.dialog { |
|||
animation-name: ajs-slideIn; |
|||
animation-timing-function: cubic-bezier( 0.175, 0.885, 0.320, 1.275 ); |
|||
} |
|||
} |
|||
//out |
|||
&.out.hidden { |
|||
.dialog { |
|||
animation-name: ajs-slideOut; |
|||
animation-timing-function: cubic-bezier( 0.600, -0.280, 0.735, 0.045 ); |
|||
} |
|||
} |
|||
} |
|||
// zoom |
|||
&.zoom { |
|||
//in |
|||
&.in:not(.hidden) { |
|||
.dialog { |
|||
animation-name: ajs-zoomIn; |
|||
} |
|||
} |
|||
//out |
|||
&.out.hidden { |
|||
.dialog { |
|||
animation-name: ajs-zoomOut; |
|||
} |
|||
} |
|||
} |
|||
// fade |
|||
&.fade { |
|||
//in |
|||
&.in:not(.hidden) { |
|||
.dialog { |
|||
animation-name: ajs-fadeIn; |
|||
} |
|||
} |
|||
//out |
|||
&.out.hidden { |
|||
.dialog { |
|||
animation-name: ajs-fadeOut; |
|||
} |
|||
} |
|||
} |
|||
// pulse |
|||
&.pulse { |
|||
//in |
|||
&.in:not(.hidden) { |
|||
.dialog { |
|||
animation-name: ajs-pulseIn; |
|||
} |
|||
} |
|||
//out |
|||
&.out.hidden { |
|||
.dialog { |
|||
animation-name: ajs-pulseOut; |
|||
} |
|||
} |
|||
} |
|||
// flip vertical |
|||
&.flipx { |
|||
//in |
|||
&.in:not(.hidden) { |
|||
.dialog { |
|||
animation-name: ajs-flipInX; |
|||
} |
|||
} |
|||
//out |
|||
&.out.hidden { |
|||
.dialog { |
|||
animation-name: ajs-flipOutX; |
|||
} |
|||
} |
|||
} |
|||
// flip vertical |
|||
&.flipy { |
|||
//in |
|||
&.in:not(.hidden) { |
|||
.dialog { |
|||
animation-name: ajs-flipInY; |
|||
} |
|||
} |
|||
//out |
|||
&.out.hidden { |
|||
.dialog { |
|||
animation-name: ajs-flipOutY; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
///////// |
|||
//pulse// |
|||
@keyframes ajs-pulseIn { |
|||
0%, 20%, 40%, 60%, 80%, 100% { |
|||
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); |
|||
} |
|||
|
|||
0% { |
|||
opacity: 0; |
|||
transform: scale3d(.3, .3, .3); |
|||
} |
|||
|
|||
20% { |
|||
transform: scale3d(1.1, 1.1, 1.1); |
|||
} |
|||
|
|||
40% { |
|||
transform: scale3d(.9, .9, .9); |
|||
} |
|||
|
|||
60% { |
|||
opacity: 1; |
|||
transform: scale3d(1.03, 1.03, 1.03); |
|||
} |
|||
|
|||
80% { |
|||
transform: scale3d(.97, .97, .97); |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
transform: scale3d(1, 1, 1); |
|||
} |
|||
} |
|||
|
|||
@keyframes ajs-pulseOut { |
|||
20% { |
|||
transform: scale3d(.9, .9, .9); |
|||
} |
|||
|
|||
50%, 55% { |
|||
opacity: 1; |
|||
transform: scale3d(1.1, 1.1, 1.1); |
|||
} |
|||
|
|||
100% { |
|||
opacity: 0; |
|||
transform: scale3d(.3, .3, .3); |
|||
} |
|||
} |
|||
//pulse// |
|||
///////// |
|||
|
|||
//////// |
|||
//zoom// |
|||
@keyframes ajs-zoomIn { |
|||
0% { |
|||
opacity: 0; |
|||
transform: scale3d(.25, .25, .25); |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
transform: scale3d(1, 1, 1); |
|||
} |
|||
} |
|||
|
|||
@keyframes ajs-zoomOut { |
|||
0% { |
|||
opacity: 1; |
|||
transform: scale3d(1, 1, 1); |
|||
} |
|||
|
|||
100% { |
|||
opacity: 0; |
|||
transform: scale3d(.25, .25, .25); |
|||
} |
|||
} |
|||
//zoom// |
|||
//////// |
|||
|
|||
|
|||
//////// |
|||
//fade// |
|||
@keyframes ajs-fadeIn { |
|||
0% { |
|||
opacity: 0; |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
} |
|||
} |
|||
|
|||
@keyframes ajs-fadeOut { |
|||
0% { |
|||
opacity: 1; |
|||
} |
|||
|
|||
100% { |
|||
opacity: 0; |
|||
} |
|||
} |
|||
//fade// |
|||
//////// |
|||
|
|||
///////// |
|||
//flipx// |
|||
@keyframes ajs-flipInX { |
|||
0% { |
|||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg); |
|||
transition-timing-function: ease-in; |
|||
opacity: 0; |
|||
} |
|||
|
|||
40% { |
|||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg); |
|||
transition-timing-function: ease-in; |
|||
} |
|||
|
|||
60% { |
|||
transform: perspective(400px) rotate3d(1, 0, 0, 10deg); |
|||
opacity: 1; |
|||
} |
|||
|
|||
80% { |
|||
transform: perspective(400px) rotate3d(1, 0, 0, -5deg); |
|||
} |
|||
|
|||
100% { |
|||
transform: perspective(400px); |
|||
} |
|||
} |
|||
|
|||
|
|||
@keyframes ajs-flipOutX { |
|||
0% { |
|||
transform: perspective(400px); |
|||
} |
|||
|
|||
30% { |
|||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg); |
|||
opacity: 1; |
|||
} |
|||
|
|||
100% { |
|||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg); |
|||
opacity: 0; |
|||
} |
|||
} |
|||
//flipx// |
|||
///////// |
|||
|
|||
|
|||
|
|||
///////// |
|||
//flipy// |
|||
@keyframes ajs-flipInY { |
|||
0% { |
|||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg); |
|||
transition-timing-function: ease-in; |
|||
opacity: 0; |
|||
} |
|||
|
|||
40% { |
|||
transform: perspective(400px) rotate3d(0, 1, 0, -20deg); |
|||
transition-timing-function: ease-in; |
|||
} |
|||
|
|||
60% { |
|||
transform: perspective(400px) rotate3d(0, 1, 0, 10deg); |
|||
opacity: 1; |
|||
} |
|||
|
|||
80% { |
|||
transform: perspective(400px) rotate3d(0, 1, 0, -5deg); |
|||
} |
|||
|
|||
100% { |
|||
transform: perspective(400px); |
|||
} |
|||
} |
|||
|
|||
@keyframes ajs-flipOutY { |
|||
0% { |
|||
transform: perspective(400px); |
|||
} |
|||
|
|||
30% { |
|||
transform: perspective(400px) rotate3d(0, 1, 0, -15deg); |
|||
opacity: 1; |
|||
} |
|||
|
|||
100% { |
|||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg); |
|||
opacity: 0; |
|||
} |
|||
} |
|||
//flipy// |
|||
///////// |
|||
|
|||
//////// |
|||
//slide// |
|||
@keyframes ajs-slideIn { |
|||
0% { |
|||
margin-top: -100%; |
|||
} |
|||
|
|||
100% { |
|||
margin-top: 5%; |
|||
} |
|||
} |
|||
|
|||
@keyframes ajs-slideOut { |
|||
0% { |
|||
margin-top: 5%; |
|||
} |
|||
|
|||
100% { |
|||
margin-top: -100%; |
|||
} |
|||
} |
|||
//slide// |
|||
//////// |
|||
|
|||
/*************** |
|||
Notifier |
|||
***************/ |
|||
|
|||
.alertify-notifier { |
|||
position: fixed; |
|||
width: 0; |
|||
overflow: visible; |
|||
z-index: 1982; |
|||
transform: translate3d(0,0,0); |
|||
|
|||
.message { |
|||
position: relative; |
|||
width: 260px; |
|||
max-height: 0; |
|||
padding: 0; |
|||
opacity: 0; |
|||
margin: 0; |
|||
transform: translate3d(0,0,0); |
|||
transition-duration: 250ms; |
|||
transition-timing-function: linear; |
|||
|
|||
&.visible { |
|||
transition-duration: 500ms; |
|||
transition-timing-function: cubic-bezier( 0.175, 0.885, 0.320, 1.275 ); |
|||
opacity: 1; |
|||
max-height: 100%; |
|||
padding: 15px; |
|||
margin-top: 10px; |
|||
} |
|||
|
|||
&.success { |
|||
background: rgba(91, 189, 114,.95); |
|||
} |
|||
|
|||
&.error { |
|||
background: rgba(217, 92, 92,.95); |
|||
} |
|||
|
|||
&.warning { |
|||
background: rgba(252, 248, 215, 0.95); |
|||
} |
|||
|
|||
.close { |
|||
position: absolute; |
|||
top: 0; |
|||
right: 0; |
|||
width:16px; |
|||
height:16px; |
|||
cursor: pointer; |
|||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABGdBTUEAALGPC/xhBQAAAFBJREFUGBl1j0EKADEIA+ve/P9f9bh1hEihNBfjVCO1v7RKVqJK4h8gM5cAPR42AkQEpSXPwMTyoi13n5N9YqJehm3Fnr7nL1D0ZEbD5OubGyC7a9gx+9eNAAAAAElFTkSuQmCC); |
|||
background-repeat: no-repeat; |
|||
background-position: center center; |
|||
background-color:rgba(0, 0, 0, 0.5); |
|||
border-top-right-radius: 2px; |
|||
} |
|||
} |
|||
|
|||
&.top { |
|||
top: 10px; |
|||
} |
|||
|
|||
&.bottom { |
|||
bottom: 10px; |
|||
} |
|||
|
|||
&.right { |
|||
right: 10px; |
|||
|
|||
.message { |
|||
right: -320px; |
|||
|
|||
&.visible { |
|||
right: 290px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&.left { |
|||
left: 10px; |
|||
|
|||
.message { |
|||
left: -300px; |
|||
|
|||
&.visible { |
|||
left: 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&.center { |
|||
left: 50%; |
|||
|
|||
.message { |
|||
transform: translateX(-50%); |
|||
|
|||
&.visible { |
|||
left: 50%; |
|||
transition-timing-function: cubic-bezier(0.57, 0.43, 0.1, 0.65); |
|||
} |
|||
} |
|||
|
|||
&.top { |
|||
.message { |
|||
top: -300px; |
|||
|
|||
&.visible { |
|||
top: 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&.bottom { |
|||
.message { |
|||
bottom: -300px; |
|||
|
|||
&.visible { |
|||
bottom: 0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,73 @@ |
|||
.alertify { |
|||
.dimmer { |
|||
background-color: #000; |
|||
opacity: .5; |
|||
} |
|||
|
|||
.dialog { |
|||
max-width: 600px; |
|||
min-height: 122px; |
|||
background-color: #fff; |
|||
border: 1px solid rgba(0,0,0,.2); |
|||
box-shadow: 0 5px 15px rgba(0,0,0,.5); |
|||
border-radius: 6px; |
|||
} |
|||
|
|||
.header { |
|||
color: #333; |
|||
border-bottom: 1px solid #e5e5e5; |
|||
border-radius: 6px 6px 0 0; |
|||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; |
|||
font-size: 18px; |
|||
} |
|||
|
|||
.body { |
|||
font-family: 'Roboto', sans-serif; |
|||
color: black; |
|||
} |
|||
|
|||
&.resizable, &.maximized:not(.resizable) { |
|||
.content { |
|||
top: 58px; |
|||
bottom: 68px; |
|||
} |
|||
} |
|||
|
|||
.footer { |
|||
background-color: #fff; |
|||
padding: 15px; |
|||
border-top: 1px solid #e5e5e5; |
|||
border-radius: 0 0 6px 6px; |
|||
} |
|||
} |
|||
|
|||
/*************** |
|||
notifier |
|||
***************/ |
|||
|
|||
.alertify-notifier { |
|||
.message { |
|||
background: rgba( 255, 255, 255, .95); |
|||
color: #000; |
|||
text-align: center; |
|||
border: solid 1px #ddd; |
|||
border-radius: 2px; |
|||
|
|||
&.success { |
|||
color: #fff; |
|||
background: rgba(91, 189, 114,.95); |
|||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5); |
|||
} |
|||
|
|||
&.error { |
|||
color: #fff; |
|||
background: rgba(217, 92, 92,.95); |
|||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5); |
|||
} |
|||
|
|||
&.warning { |
|||
background: rgba(252, 248, 215, 0.95); |
|||
border-color: #999; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,91 @@ |
|||
.alertify { |
|||
|
|||
.dialog { |
|||
background-color: white; |
|||
box-shadow: 0px 15px 20px 0px rgba(0, 0, 0, 0.25); |
|||
border-radius: 2px; |
|||
} |
|||
|
|||
.header { |
|||
color: black; |
|||
font-weight: bold; |
|||
background: #fafafa; |
|||
border-bottom: #eee 1px solid; |
|||
border-radius: 2px 2px 0 0; |
|||
} |
|||
|
|||
.body { |
|||
color: black; |
|||
|
|||
.content { |
|||
|
|||
.input { |
|||
display: block; |
|||
width: 100%; |
|||
padding: 8px; |
|||
margin: 4px; |
|||
border-radius: 2px; |
|||
border: 1px solid #CCC; |
|||
} |
|||
|
|||
p { |
|||
margin: 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.footer { |
|||
background: #fbfbfb; |
|||
border-top: #eee 1px solid; |
|||
border-radius: 0 0 2px 2px; |
|||
|
|||
.buttons { |
|||
.button { |
|||
background-color: transparent; |
|||
color: #000; |
|||
border: 0; |
|||
font-size: 14px; |
|||
font-weight: bold; |
|||
text-transform: uppercase; |
|||
//&:focus{ |
|||
// outline:auto 5px #498EFF; |
|||
// box-shadow: 0px 0px 4px 0px #498EFF; |
|||
//} |
|||
&.ok { |
|||
color: #3593D2; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*************** |
|||
notifier |
|||
***************/ |
|||
|
|||
.alertify-notifier { |
|||
.message { |
|||
background: rgba( 255, 255, 255, .95); |
|||
color: #000; |
|||
text-align: center; |
|||
border: solid 1px #ddd; |
|||
border-radius: 2px; |
|||
|
|||
&.success { |
|||
color: #fff; |
|||
background: rgba(91, 189, 114,.95); |
|||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5); |
|||
} |
|||
|
|||
&.error { |
|||
color: #fff; |
|||
background: rgba(217, 92, 92,.95); |
|||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5); |
|||
} |
|||
|
|||
&.warning { |
|||
background: rgba(252, 248, 215, 0.95); |
|||
border-color: #999; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,102 @@ |
|||
.alertify { |
|||
.dimmer { |
|||
background-color: rgba(0,0,0,.85); |
|||
opacity: 1; |
|||
} |
|||
|
|||
.dialog { |
|||
max-width: 50%; |
|||
min-height: 137px; |
|||
background-color: #F4F4F4; |
|||
border: 1px solid #DDD; |
|||
box-shadow: none; |
|||
border-radius: 5px; |
|||
} |
|||
|
|||
.header { |
|||
padding: 1.5rem 2rem; |
|||
border-bottom: none; |
|||
border-radius: 5px 5px 0 0; |
|||
color: #555; |
|||
background-color: #fff; |
|||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; |
|||
font-size: 1.6em; |
|||
font-weight: 700; |
|||
} |
|||
|
|||
.body { |
|||
font-family: 'Roboto', sans-serif; |
|||
color: #555; |
|||
|
|||
.content { |
|||
.input { |
|||
width: 100%; |
|||
margin: 0; |
|||
padding: .65em 1em; |
|||
font-size: 1em; |
|||
background-color: #FFF; |
|||
border: 1px solid rgba(0,0,0,.15); |
|||
outline: 0; |
|||
color: rgba(0,0,0,.7); |
|||
border-radius: .3125em; |
|||
transition: background-color .3s ease-out,box-shadow .2s ease,border-color .2s ease; |
|||
box-sizing: border-box; |
|||
|
|||
&:active { |
|||
border-color: rgba(0, 0, 0, 0.3); |
|||
background-color: #FAFAFA; |
|||
} |
|||
|
|||
&:focus { |
|||
border-color: rgba(0, 0, 0, 0.2); |
|||
color: rgba(0, 0, 0, 0.85); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
&.resizable, &.maximized:not(.resizable) { |
|||
.content { |
|||
top: 64px; |
|||
bottom: 74px; |
|||
} |
|||
} |
|||
|
|||
.footer { |
|||
background-color: #fff; |
|||
padding: 1rem 2rem; |
|||
border-top: none; |
|||
border-radius: 0 0 5px 5px; |
|||
} |
|||
} |
|||
|
|||
/*************** |
|||
notifier |
|||
***************/ |
|||
|
|||
.alertify-notifier { |
|||
.message { |
|||
background: rgba( 255, 255, 255, .95); |
|||
color: #000; |
|||
text-align: center; |
|||
border: solid 1px #ddd; |
|||
border-radius: 2px; |
|||
|
|||
&.success { |
|||
color: #fff; |
|||
background: rgba(91, 189, 114,.95); |
|||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5); |
|||
} |
|||
|
|||
&.error { |
|||
color: #fff; |
|||
background: rgba(217, 92, 92,.95); |
|||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5); |
|||
} |
|||
|
|||
&.warning { |
|||
background: rgba(252, 248, 215, 0.95); |
|||
border-color: #999; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,185 @@ |
|||
1.0.10 / 2018-02-15 |
|||
------------------ |
|||
|
|||
- Use .concat instead of + for arrays, #122. |
|||
|
|||
|
|||
1.0.9 / 2016-09-29 |
|||
------------------ |
|||
|
|||
- Rerelease after 1.0.8 - deps cleanup. |
|||
|
|||
|
|||
1.0.8 / 2016-09-29 |
|||
------------------ |
|||
|
|||
- Maintenance (deps bump, fix node 6.5+ tests, coverage report). |
|||
|
|||
|
|||
1.0.7 / 2016-03-17 |
|||
------------------ |
|||
|
|||
- Teach `addArgument` to accept string arg names. #97, @tomxtobin. |
|||
|
|||
|
|||
1.0.6 / 2016-02-06 |
|||
------------------ |
|||
|
|||
- Maintenance: moved to eslint & updated CS. |
|||
|
|||
|
|||
1.0.5 / 2016-02-05 |
|||
------------------ |
|||
|
|||
- Removed lodash dependency to significantly reduce install size. |
|||
Thanks to @mourner. |
|||
|
|||
|
|||
1.0.4 / 2016-01-17 |
|||
------------------ |
|||
|
|||
- Maintenance: lodash update to 4.0.0. |
|||
|
|||
|
|||
1.0.3 / 2015-10-27 |
|||
------------------ |
|||
|
|||
- Fix parse `=` in args: `--examplepath="C:\myfolder\env=x64"`. #84, @CatWithApple. |
|||
|
|||
|
|||
1.0.2 / 2015-03-22 |
|||
------------------ |
|||
|
|||
- Relaxed lodash version dependency. |
|||
|
|||
|
|||
1.0.1 / 2015-02-20 |
|||
------------------ |
|||
|
|||
- Changed dependencies to be compatible with ancient nodejs. |
|||
|
|||
|
|||
1.0.0 / 2015-02-19 |
|||
------------------ |
|||
|
|||
- Maintenance release. |
|||
- Replaced `underscore` with `lodash`. |
|||
- Bumped version to 1.0.0 to better reflect semver meaning. |
|||
- HISTORY.md -> CHANGELOG.md |
|||
|
|||
|
|||
0.1.16 / 2013-12-01 |
|||
------------------- |
|||
|
|||
- Maintenance release. Updated dependencies and docs. |
|||
|
|||
|
|||
0.1.15 / 2013-05-13 |
|||
------------------- |
|||
|
|||
- Fixed #55, @trebor89 |
|||
|
|||
|
|||
0.1.14 / 2013-05-12 |
|||
------------------- |
|||
|
|||
- Fixed #62, @maxtaco |
|||
|
|||
|
|||
0.1.13 / 2013-04-08 |
|||
------------------- |
|||
|
|||
- Added `.npmignore` to reduce package size |
|||
|
|||
|
|||
0.1.12 / 2013-02-10 |
|||
------------------- |
|||
|
|||
- Fixed conflictHandler (#46), @hpaulj |
|||
|
|||
|
|||
0.1.11 / 2013-02-07 |
|||
------------------- |
|||
|
|||
- Multiple bugfixes, @hpaulj |
|||
- Added 70+ tests (ported from python), @hpaulj |
|||
- Added conflictHandler, @applepicke |
|||
- Added fromfilePrefixChar, @hpaulj |
|||
|
|||
|
|||
0.1.10 / 2012-12-30 |
|||
------------------- |
|||
|
|||
- Added [mutual exclusion](http://docs.python.org/dev/library/argparse.html#mutual-exclusion) |
|||
support, thanks to @hpaulj |
|||
- Fixed options check for `storeConst` & `appendConst` actions, thanks to @hpaulj |
|||
|
|||
|
|||
0.1.9 / 2012-12-27 |
|||
------------------ |
|||
|
|||
- Fixed option dest interferens with other options (issue #23), thanks to @hpaulj |
|||
- Fixed default value behavior with `*` positionals, thanks to @hpaulj |
|||
- Improve `getDefault()` behavior, thanks to @hpaulj |
|||
- Imrove negative argument parsing, thanks to @hpaulj |
|||
|
|||
|
|||
0.1.8 / 2012-12-01 |
|||
------------------ |
|||
|
|||
- Fixed parser parents (issue #19), thanks to @hpaulj |
|||
- Fixed negative argument parse (issue #20), thanks to @hpaulj |
|||
|
|||
|
|||
0.1.7 / 2012-10-14 |
|||
------------------ |
|||
|
|||
- Fixed 'choices' argument parse (issue #16) |
|||
- Fixed stderr output (issue #15) |
|||
|
|||
|
|||
0.1.6 / 2012-09-09 |
|||
------------------ |
|||
|
|||
- Fixed check for conflict of options (thanks to @tomxtobin) |
|||
|
|||
|
|||
0.1.5 / 2012-09-03 |
|||
------------------ |
|||
|
|||
- Fix parser #setDefaults method (thanks to @tomxtobin) |
|||
|
|||
|
|||
0.1.4 / 2012-07-30 |
|||
------------------ |
|||
|
|||
- Fixed pseudo-argument support (thanks to @CGamesPlay) |
|||
- Fixed addHelp default (should be true), if not set (thanks to @benblank) |
|||
|
|||
|
|||
0.1.3 / 2012-06-27 |
|||
------------------ |
|||
|
|||
- Fixed formatter api name: Formatter -> HelpFormatter |
|||
|
|||
|
|||
0.1.2 / 2012-05-29 |
|||
------------------ |
|||
|
|||
- Added basic tests |
|||
- Removed excess whitespace in help |
|||
- Fixed error reporting, when parcer with subcommands |
|||
called with empty arguments |
|||
|
|||
|
|||
0.1.1 / 2012-05-23 |
|||
------------------ |
|||
|
|||
- Fixed line wrapping in help formatter |
|||
- Added better error reporting on invalid arguments |
|||
|
|||
|
|||
0.1.0 / 2012-05-16 |
|||
------------------ |
|||
|
|||
- First release. |
@ -0,0 +1,21 @@ |
|||
(The MIT License) |
|||
|
|||
Copyright (C) 2012 by Vitaly Puzrin |
|||
|
|||
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,257 @@ |
|||
argparse |
|||
======== |
|||
|
|||
[![Build Status](https://secure.travis-ci.org/nodeca/argparse.svg?branch=master)](http://travis-ci.org/nodeca/argparse) |
|||
[![NPM version](https://img.shields.io/npm/v/argparse.svg)](https://www.npmjs.org/package/argparse) |
|||
|
|||
CLI arguments parser for node.js. Javascript port of python's |
|||
[argparse](http://docs.python.org/dev/library/argparse.html) module |
|||
(original version 3.2). That's a full port, except some very rare options, |
|||
recorded in issue tracker. |
|||
|
|||
**NB. Difference with original.** |
|||
|
|||
- Method names changed to camelCase. See [generated docs](http://nodeca.github.com/argparse/). |
|||
- Use `defaultValue` instead of `default`. |
|||
- Use `argparse.Const.REMAINDER` instead of `argparse.REMAINDER`, and |
|||
similarly for constant values `OPTIONAL`, `ZERO_OR_MORE`, and `ONE_OR_MORE` |
|||
(aliases for `nargs` values `'?'`, `'*'`, `'+'`, respectively), and |
|||
`SUPPRESS`. |
|||
|
|||
|
|||
Example |
|||
======= |
|||
|
|||
test.js file: |
|||
|
|||
```javascript |
|||
#!/usr/bin/env node |
|||
'use strict'; |
|||
|
|||
var ArgumentParser = require('../lib/argparse').ArgumentParser; |
|||
var parser = new ArgumentParser({ |
|||
version: '0.0.1', |
|||
addHelp:true, |
|||
description: 'Argparse example' |
|||
}); |
|||
parser.addArgument( |
|||
[ '-f', '--foo' ], |
|||
{ |
|||
help: 'foo bar' |
|||
} |
|||
); |
|||
parser.addArgument( |
|||
[ '-b', '--bar' ], |
|||
{ |
|||
help: 'bar foo' |
|||
} |
|||
); |
|||
parser.addArgument( |
|||
'--baz', |
|||
{ |
|||
help: 'baz bar' |
|||
} |
|||
); |
|||
var args = parser.parseArgs(); |
|||
console.dir(args); |
|||
``` |
|||
|
|||
Display help: |
|||
|
|||
``` |
|||
$ ./test.js -h |
|||
usage: example.js [-h] [-v] [-f FOO] [-b BAR] [--baz BAZ] |
|||
|
|||
Argparse example |
|||
|
|||
Optional arguments: |
|||
-h, --help Show this help message and exit. |
|||
-v, --version Show program's version number and exit. |
|||
-f FOO, --foo FOO foo bar |
|||
-b BAR, --bar BAR bar foo |
|||
--baz BAZ baz bar |
|||
``` |
|||
|
|||
Parse arguments: |
|||
|
|||
``` |
|||
$ ./test.js -f=3 --bar=4 --baz 5 |
|||
{ foo: '3', bar: '4', baz: '5' } |
|||
``` |
|||
|
|||
More [examples](https://github.com/nodeca/argparse/tree/master/examples). |
|||
|
|||
|
|||
ArgumentParser objects |
|||
====================== |
|||
|
|||
``` |
|||
new ArgumentParser({parameters hash}); |
|||
``` |
|||
|
|||
Creates a new ArgumentParser object. |
|||
|
|||
**Supported params:** |
|||
|
|||
- ```description``` - Text to display before the argument help. |
|||
- ```epilog``` - Text to display after the argument help. |
|||
- ```addHelp``` - Add a -h/–help option to the parser. (default: true) |
|||
- ```argumentDefault``` - Set the global default value for arguments. (default: null) |
|||
- ```parents``` - A list of ArgumentParser objects whose arguments should also be included. |
|||
- ```prefixChars``` - The set of characters that prefix optional arguments. (default: ‘-‘) |
|||
- ```formatterClass``` - A class for customizing the help output. |
|||
- ```prog``` - The name of the program (default: `path.basename(process.argv[1])`) |
|||
- ```usage``` - The string describing the program usage (default: generated) |
|||
- ```conflictHandler``` - Usually unnecessary, defines strategy for resolving conflicting optionals. |
|||
|
|||
**Not supported yet** |
|||
|
|||
- ```fromfilePrefixChars``` - The set of characters that prefix files from which additional arguments should be read. |
|||
|
|||
|
|||
Details in [original ArgumentParser guide](http://docs.python.org/dev/library/argparse.html#argumentparser-objects) |
|||
|
|||
|
|||
addArgument() method |
|||
==================== |
|||
|
|||
``` |
|||
ArgumentParser.addArgument(name or flag or [name] or [flags...], {options}) |
|||
``` |
|||
|
|||
Defines how a single command-line argument should be parsed. |
|||
|
|||
- ```name or flag or [name] or [flags...]``` - Either a positional name |
|||
(e.g., `'foo'`), a single option (e.g., `'-f'` or `'--foo'`), an array |
|||
of a single positional name (e.g., `['foo']`), or an array of options |
|||
(e.g., `['-f', '--foo']`). |
|||
|
|||
Options: |
|||
|
|||
- ```action``` - The basic type of action to be taken when this argument is encountered at the command line. |
|||
- ```nargs```- The number of command-line arguments that should be consumed. |
|||
- ```constant``` - A constant value required by some action and nargs selections. |
|||
- ```defaultValue``` - The value produced if the argument is absent from the command line. |
|||
- ```type``` - The type to which the command-line argument should be converted. |
|||
- ```choices``` - A container of the allowable values for the argument. |
|||
- ```required``` - Whether or not the command-line option may be omitted (optionals only). |
|||
- ```help``` - A brief description of what the argument does. |
|||
- ```metavar``` - A name for the argument in usage messages. |
|||
- ```dest``` - The name of the attribute to be added to the object returned by parseArgs(). |
|||
|
|||
Details in [original add_argument guide](http://docs.python.org/dev/library/argparse.html#the-add-argument-method) |
|||
|
|||
|
|||
Action (some details) |
|||
================ |
|||
|
|||
ArgumentParser objects associate command-line arguments with actions. |
|||
These actions can do just about anything with the command-line arguments associated |
|||
with them, though most actions simply add an attribute to the object returned by |
|||
parseArgs(). The action keyword argument specifies how the command-line arguments |
|||
should be handled. The supported actions are: |
|||
|
|||
- ```store``` - Just stores the argument’s value. This is the default action. |
|||
- ```storeConst``` - Stores value, specified by the const keyword argument. |
|||
(Note that the const keyword argument defaults to the rather unhelpful None.) |
|||
The 'storeConst' action is most commonly used with optional arguments, that |
|||
specify some sort of flag. |
|||
- ```storeTrue``` and ```storeFalse``` - Stores values True and False |
|||
respectively. These are special cases of 'storeConst'. |
|||
- ```append``` - Stores a list, and appends each argument value to the list. |
|||
This is useful to allow an option to be specified multiple times. |
|||
- ```appendConst``` - Stores a list, and appends value, specified by the |
|||
const keyword argument to the list. (Note, that the const keyword argument defaults |
|||
is None.) The 'appendConst' action is typically used when multiple arguments need |
|||
to store constants to the same list. |
|||
- ```count``` - Counts the number of times a keyword argument occurs. For example, |
|||
used for increasing verbosity levels. |
|||
- ```help``` - Prints a complete help message for all the options in the current |
|||
parser and then exits. By default a help action is automatically added to the parser. |
|||
See ArgumentParser for details of how the output is created. |
|||
- ```version``` - Prints version information and exit. Expects a `version=` |
|||
keyword argument in the addArgument() call. |
|||
|
|||
Details in [original action guide](http://docs.python.org/dev/library/argparse.html#action) |
|||
|
|||
|
|||
Sub-commands |
|||
============ |
|||
|
|||
ArgumentParser.addSubparsers() |
|||
|
|||
Many programs split their functionality into a number of sub-commands, for |
|||
example, the svn program can invoke sub-commands like `svn checkout`, `svn update`, |
|||
and `svn commit`. Splitting up functionality this way can be a particularly good |
|||
idea when a program performs several different functions which require different |
|||
kinds of command-line arguments. `ArgumentParser` supports creation of such |
|||
sub-commands with `addSubparsers()` method. The `addSubparsers()` method is |
|||
normally called with no arguments and returns an special action object. |
|||
This object has a single method `addParser()`, which takes a command name and |
|||
any `ArgumentParser` constructor arguments, and returns an `ArgumentParser` object |
|||
that can be modified as usual. |
|||
|
|||
Example: |
|||
|
|||
sub_commands.js |
|||
```javascript |
|||
#!/usr/bin/env node |
|||
'use strict'; |
|||
|
|||
var ArgumentParser = require('../lib/argparse').ArgumentParser; |
|||
var parser = new ArgumentParser({ |
|||
version: '0.0.1', |
|||
addHelp:true, |
|||
description: 'Argparse examples: sub-commands', |
|||
}); |
|||
|
|||
var subparsers = parser.addSubparsers({ |
|||
title:'subcommands', |
|||
dest:"subcommand_name" |
|||
}); |
|||
|
|||
var bar = subparsers.addParser('c1', {addHelp:true}); |
|||
bar.addArgument( |
|||
[ '-f', '--foo' ], |
|||
{ |
|||
action: 'store', |
|||
help: 'foo3 bar3' |
|||
} |
|||
); |
|||
var bar = subparsers.addParser( |
|||
'c2', |
|||
{aliases:['co'], addHelp:true} |
|||
); |
|||
bar.addArgument( |
|||
[ '-b', '--bar' ], |
|||
{ |
|||
action: 'store', |
|||
type: 'int', |
|||
help: 'foo3 bar3' |
|||
} |
|||
); |
|||
|
|||
var args = parser.parseArgs(); |
|||
console.dir(args); |
|||
|
|||
``` |
|||
|
|||
Details in [original sub-commands guide](http://docs.python.org/dev/library/argparse.html#sub-commands) |
|||
|
|||
|
|||
Contributors |
|||
============ |
|||
|
|||
- [Eugene Shkuropat](https://github.com/shkuropat) |
|||
- [Paul Jacobson](https://github.com/hpaulj) |
|||
|
|||
[others](https://github.com/nodeca/argparse/graphs/contributors) |
|||
|
|||
License |
|||
======= |
|||
|
|||
Copyright (c) 2012 [Vitaly Puzrin](https://github.com/puzrin). |
|||
Released under the MIT license. See |
|||
[LICENSE](https://github.com/nodeca/argparse/blob/master/LICENSE) for details. |
|||
|
|||
|
@ -0,0 +1,3 @@ |
|||
'use strict'; |
|||
|
|||
module.exports = require('./lib/argparse'); |
@ -0,0 +1,146 @@ |
|||
/** |
|||
* class Action |
|||
* |
|||
* Base class for all actions |
|||
* Do not call in your code, use this class only for inherits your own action |
|||
* |
|||
* Information about how to convert command line strings to Javascript objects. |
|||
* Action objects are used by an ArgumentParser to represent the information |
|||
* needed to parse a single argument from one or more strings from the command |
|||
* line. The keyword arguments to the Action constructor are also all attributes |
|||
* of Action instances. |
|||
* |
|||
* ##### Allowed keywords: |
|||
* |
|||
* - `store` |
|||
* - `storeConstant` |
|||
* - `storeTrue` |
|||
* - `storeFalse` |
|||
* - `append` |
|||
* - `appendConstant` |
|||
* - `count` |
|||
* - `help` |
|||
* - `version` |
|||
* |
|||
* Information about action options see [[Action.new]] |
|||
* |
|||
* See also [original guide](http://docs.python.org/dev/library/argparse.html#action)
|
|||
* |
|||
**/ |
|||
|
|||
'use strict'; |
|||
|
|||
|
|||
// Constants
|
|||
var c = require('./const'); |
|||
|
|||
|
|||
/** |
|||
* new Action(options) |
|||
* |
|||
* Base class for all actions. Used only for inherits |
|||
* |
|||
* |
|||
* ##### Options: |
|||
* |
|||
* - `optionStrings` A list of command-line option strings for the action. |
|||
* - `dest` Attribute to hold the created object(s) |
|||
* - `nargs` The number of command-line arguments that should be consumed. |
|||
* By default, one argument will be consumed and a single value will be |
|||
* produced. |
|||
* - `constant` Default value for an action with no value. |
|||
* - `defaultValue` The value to be produced if the option is not specified. |
|||
* - `type` Cast to 'string'|'int'|'float'|'complex'|function (string). If |
|||
* None, 'string'. |
|||
* - `choices` The choices available. |
|||
* - `required` True if the action must always be specified at the command |
|||
* line. |
|||
* - `help` The help describing the argument. |
|||
* - `metavar` The name to be used for the option's argument with the help |
|||
* string. If None, the 'dest' value will be used as the name. |
|||
* |
|||
* ##### nargs supported values: |
|||
* |
|||
* - `N` (an integer) consumes N arguments (and produces a list) |
|||
* - `?` consumes zero or one arguments |
|||
* - `*` consumes zero or more arguments (and produces a list) |
|||
* - `+` consumes one or more arguments (and produces a list) |
|||
* |
|||
* Note: that the difference between the default and nargs=1 is that with the |
|||
* default, a single value will be produced, while with nargs=1, a list |
|||
* containing a single value will be produced. |
|||
**/ |
|||
var Action = module.exports = function Action(options) { |
|||
options = options || {}; |
|||
this.optionStrings = options.optionStrings || []; |
|||
this.dest = options.dest; |
|||
this.nargs = typeof options.nargs !== 'undefined' ? options.nargs : null; |
|||
this.constant = typeof options.constant !== 'undefined' ? options.constant : null; |
|||
this.defaultValue = options.defaultValue; |
|||
this.type = typeof options.type !== 'undefined' ? options.type : null; |
|||
this.choices = typeof options.choices !== 'undefined' ? options.choices : null; |
|||
this.required = typeof options.required !== 'undefined' ? options.required : false; |
|||
this.help = typeof options.help !== 'undefined' ? options.help : null; |
|||
this.metavar = typeof options.metavar !== 'undefined' ? options.metavar : null; |
|||
|
|||
if (!(this.optionStrings instanceof Array)) { |
|||
throw new Error('optionStrings should be an array'); |
|||
} |
|||
if (typeof this.required !== 'undefined' && typeof this.required !== 'boolean') { |
|||
throw new Error('required should be a boolean'); |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Action#getName -> String |
|||
* |
|||
* Tells action name |
|||
**/ |
|||
Action.prototype.getName = function () { |
|||
if (this.optionStrings.length > 0) { |
|||
return this.optionStrings.join('/'); |
|||
} else if (this.metavar !== null && this.metavar !== c.SUPPRESS) { |
|||
return this.metavar; |
|||
} else if (typeof this.dest !== 'undefined' && this.dest !== c.SUPPRESS) { |
|||
return this.dest; |
|||
} |
|||
return null; |
|||
}; |
|||
|
|||
/** |
|||
* Action#isOptional -> Boolean |
|||
* |
|||
* Return true if optional |
|||
**/ |
|||
Action.prototype.isOptional = function () { |
|||
return !this.isPositional(); |
|||
}; |
|||
|
|||
/** |
|||
* Action#isPositional -> Boolean |
|||
* |
|||
* Return true if positional |
|||
**/ |
|||
Action.prototype.isPositional = function () { |
|||
return (this.optionStrings.length === 0); |
|||
}; |
|||
|
|||
/** |
|||
* Action#call(parser, namespace, values, optionString) -> Void |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Call the action. Should be implemented in inherited classes |
|||
* |
|||
* ##### Example |
|||
* |
|||
* ActionCount.prototype.call = function (parser, namespace, values, optionString) { |
|||
* namespace.set(this.dest, (namespace[this.dest] || 0) + 1); |
|||
* }; |
|||
* |
|||
**/ |
|||
Action.prototype.call = function () { |
|||
throw new Error('.call() not defined');// Not Implemented error
|
|||
}; |
@ -0,0 +1,53 @@ |
|||
/*:nodoc:* |
|||
* class ActionAppend |
|||
* |
|||
* This action stores a list, and appends each argument value to the list. |
|||
* This is useful to allow an option to be specified multiple times. |
|||
* This class inherided from [[Action]] |
|||
* |
|||
**/ |
|||
|
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var Action = require('../action'); |
|||
|
|||
// Constants
|
|||
var c = require('../const'); |
|||
|
|||
/*:nodoc:* |
|||
* new ActionAppend(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
* Note: options.nargs should be optional for constants |
|||
* and more then zero for other |
|||
**/ |
|||
var ActionAppend = module.exports = function ActionAppend(options) { |
|||
options = options || {}; |
|||
if (this.nargs <= 0) { |
|||
throw new Error('nargs for append actions must be > 0; if arg ' + |
|||
'strings are not supplying the value to append, ' + |
|||
'the append const action may be more appropriate'); |
|||
} |
|||
if (!!this.constant && this.nargs !== c.OPTIONAL) { |
|||
throw new Error('nargs must be OPTIONAL to supply const'); |
|||
} |
|||
Action.call(this, options); |
|||
}; |
|||
util.inherits(ActionAppend, Action); |
|||
|
|||
/*:nodoc:* |
|||
* ActionAppend#call(parser, namespace, values, optionString) -> Void |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Call the action. Save result in namespace object |
|||
**/ |
|||
ActionAppend.prototype.call = function (parser, namespace, values) { |
|||
var items = (namespace[this.dest] || []).slice(); |
|||
items.push(values); |
|||
namespace.set(this.dest, items); |
|||
}; |
@ -0,0 +1,47 @@ |
|||
/*:nodoc:* |
|||
* class ActionAppendConstant |
|||
* |
|||
* This stores a list, and appends the value specified by |
|||
* the const keyword argument to the list. |
|||
* (Note that the const keyword argument defaults to null.) |
|||
* The 'appendConst' action is typically useful when multiple |
|||
* arguments need to store constants to the same list. |
|||
* |
|||
* This class inherited from [[Action]] |
|||
**/ |
|||
|
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var Action = require('../../action'); |
|||
|
|||
/*:nodoc:* |
|||
* new ActionAppendConstant(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
**/ |
|||
var ActionAppendConstant = module.exports = function ActionAppendConstant(options) { |
|||
options = options || {}; |
|||
options.nargs = 0; |
|||
if (typeof options.constant === 'undefined') { |
|||
throw new Error('constant option is required for appendAction'); |
|||
} |
|||
Action.call(this, options); |
|||
}; |
|||
util.inherits(ActionAppendConstant, Action); |
|||
|
|||
/*:nodoc:* |
|||
* ActionAppendConstant#call(parser, namespace, values, optionString) -> Void |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Call the action. Save result in namespace object |
|||
**/ |
|||
ActionAppendConstant.prototype.call = function (parser, namespace) { |
|||
var items = [].concat(namespace[this.dest] || []); |
|||
items.push(this.constant); |
|||
namespace.set(this.dest, items); |
|||
}; |
@ -0,0 +1,40 @@ |
|||
/*:nodoc:* |
|||
* class ActionCount |
|||
* |
|||
* This counts the number of times a keyword argument occurs. |
|||
* For example, this is useful for increasing verbosity levels |
|||
* |
|||
* This class inherided from [[Action]] |
|||
* |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var Action = require('../action'); |
|||
|
|||
/*:nodoc:* |
|||
* new ActionCount(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
**/ |
|||
var ActionCount = module.exports = function ActionCount(options) { |
|||
options = options || {}; |
|||
options.nargs = 0; |
|||
|
|||
Action.call(this, options); |
|||
}; |
|||
util.inherits(ActionCount, Action); |
|||
|
|||
/*:nodoc:* |
|||
* ActionCount#call(parser, namespace, values, optionString) -> Void |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Call the action. Save result in namespace object |
|||
**/ |
|||
ActionCount.prototype.call = function (parser, namespace) { |
|||
namespace.set(this.dest, (namespace[this.dest] || 0) + 1); |
|||
}; |
@ -0,0 +1,47 @@ |
|||
/*:nodoc:* |
|||
* class ActionHelp |
|||
* |
|||
* Support action for printing help |
|||
* This class inherided from [[Action]] |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var Action = require('../action'); |
|||
|
|||
// Constants
|
|||
var c = require('../const'); |
|||
|
|||
/*:nodoc:* |
|||
* new ActionHelp(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
**/ |
|||
var ActionHelp = module.exports = function ActionHelp(options) { |
|||
options = options || {}; |
|||
if (options.defaultValue !== null) { |
|||
options.defaultValue = options.defaultValue; |
|||
} else { |
|||
options.defaultValue = c.SUPPRESS; |
|||
} |
|||
options.dest = (options.dest !== null ? options.dest : c.SUPPRESS); |
|||
options.nargs = 0; |
|||
Action.call(this, options); |
|||
|
|||
}; |
|||
util.inherits(ActionHelp, Action); |
|||
|
|||
/*:nodoc:* |
|||
* ActionHelp#call(parser, namespace, values, optionString) |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Print help and exit |
|||
**/ |
|||
ActionHelp.prototype.call = function (parser) { |
|||
parser.printHelp(); |
|||
parser.exit(); |
|||
}; |
@ -0,0 +1,50 @@ |
|||
/*:nodoc:* |
|||
* class ActionStore |
|||
* |
|||
* This action just stores the argument’s value. This is the default action. |
|||
* |
|||
* This class inherited from [[Action]] |
|||
* |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var Action = require('../action'); |
|||
|
|||
// Constants
|
|||
var c = require('../const'); |
|||
|
|||
|
|||
/*:nodoc:* |
|||
* new ActionStore(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
**/ |
|||
var ActionStore = module.exports = function ActionStore(options) { |
|||
options = options || {}; |
|||
if (this.nargs <= 0) { |
|||
throw new Error('nargs for store actions must be > 0; if you ' + |
|||
'have nothing to store, actions such as store ' + |
|||
'true or store const may be more appropriate'); |
|||
|
|||
} |
|||
if (typeof this.constant !== 'undefined' && this.nargs !== c.OPTIONAL) { |
|||
throw new Error('nargs must be OPTIONAL to supply const'); |
|||
} |
|||
Action.call(this, options); |
|||
}; |
|||
util.inherits(ActionStore, Action); |
|||
|
|||
/*:nodoc:* |
|||
* ActionStore#call(parser, namespace, values, optionString) -> Void |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Call the action. Save result in namespace object |
|||
**/ |
|||
ActionStore.prototype.call = function (parser, namespace, values) { |
|||
namespace.set(this.dest, values); |
|||
}; |
@ -0,0 +1,43 @@ |
|||
/*:nodoc:* |
|||
* class ActionStoreConstant |
|||
* |
|||
* This action stores the value specified by the const keyword argument. |
|||
* (Note that the const keyword argument defaults to the rather unhelpful null.) |
|||
* The 'store_const' action is most commonly used with optional |
|||
* arguments that specify some sort of flag. |
|||
* |
|||
* This class inherited from [[Action]] |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var Action = require('../../action'); |
|||
|
|||
/*:nodoc:* |
|||
* new ActionStoreConstant(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
**/ |
|||
var ActionStoreConstant = module.exports = function ActionStoreConstant(options) { |
|||
options = options || {}; |
|||
options.nargs = 0; |
|||
if (typeof options.constant === 'undefined') { |
|||
throw new Error('constant option is required for storeAction'); |
|||
} |
|||
Action.call(this, options); |
|||
}; |
|||
util.inherits(ActionStoreConstant, Action); |
|||
|
|||
/*:nodoc:* |
|||
* ActionStoreConstant#call(parser, namespace, values, optionString) -> Void |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Call the action. Save result in namespace object |
|||
**/ |
|||
ActionStoreConstant.prototype.call = function (parser, namespace) { |
|||
namespace.set(this.dest, this.constant); |
|||
}; |
@ -0,0 +1,27 @@ |
|||
/*:nodoc:* |
|||
* class ActionStoreFalse |
|||
* |
|||
* This action store the values False respectively. |
|||
* This is special cases of 'storeConst' |
|||
* |
|||
* This class inherited from [[Action]] |
|||
**/ |
|||
|
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var ActionStoreConstant = require('./constant'); |
|||
|
|||
/*:nodoc:* |
|||
* new ActionStoreFalse(options) |
|||
* - options (object): hash of options see [[Action.new]] |
|||
* |
|||
**/ |
|||
var ActionStoreFalse = module.exports = function ActionStoreFalse(options) { |
|||
options = options || {}; |
|||
options.constant = false; |
|||
options.defaultValue = options.defaultValue !== null ? options.defaultValue : true; |
|||
ActionStoreConstant.call(this, options); |
|||
}; |
|||
util.inherits(ActionStoreFalse, ActionStoreConstant); |
@ -0,0 +1,26 @@ |
|||
/*:nodoc:* |
|||
* class ActionStoreTrue |
|||
* |
|||
* This action store the values True respectively. |
|||
* This isspecial cases of 'storeConst' |
|||
* |
|||
* This class inherited from [[Action]] |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var ActionStoreConstant = require('./constant'); |
|||
|
|||
/*:nodoc:* |
|||
* new ActionStoreTrue(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
**/ |
|||
var ActionStoreTrue = module.exports = function ActionStoreTrue(options) { |
|||
options = options || {}; |
|||
options.constant = true; |
|||
options.defaultValue = options.defaultValue !== null ? options.defaultValue : false; |
|||
ActionStoreConstant.call(this, options); |
|||
}; |
|||
util.inherits(ActionStoreTrue, ActionStoreConstant); |
@ -0,0 +1,149 @@ |
|||
/** internal |
|||
* class ActionSubparsers |
|||
* |
|||
* Support the creation of such sub-commands with the addSubparsers() |
|||
* |
|||
* This class inherited from [[Action]] |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
var format = require('util').format; |
|||
|
|||
|
|||
var Action = require('../action'); |
|||
|
|||
// Constants
|
|||
var c = require('../const'); |
|||
|
|||
// Errors
|
|||
var argumentErrorHelper = require('../argument/error'); |
|||
|
|||
|
|||
/*:nodoc:* |
|||
* new ChoicesPseudoAction(name, help) |
|||
* |
|||
* Create pseudo action for correct help text |
|||
* |
|||
**/ |
|||
function ChoicesPseudoAction(name, help) { |
|||
var options = { |
|||
optionStrings: [], |
|||
dest: name, |
|||
help: help |
|||
}; |
|||
|
|||
Action.call(this, options); |
|||
} |
|||
|
|||
util.inherits(ChoicesPseudoAction, Action); |
|||
|
|||
/** |
|||
* new ActionSubparsers(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
**/ |
|||
function ActionSubparsers(options) { |
|||
options = options || {}; |
|||
options.dest = options.dest || c.SUPPRESS; |
|||
options.nargs = c.PARSER; |
|||
|
|||
this.debug = (options.debug === true); |
|||
|
|||
this._progPrefix = options.prog; |
|||
this._parserClass = options.parserClass; |
|||
this._nameParserMap = {}; |
|||
this._choicesActions = []; |
|||
|
|||
options.choices = this._nameParserMap; |
|||
Action.call(this, options); |
|||
} |
|||
|
|||
util.inherits(ActionSubparsers, Action); |
|||
|
|||
/*:nodoc:* |
|||
* ActionSubparsers#addParser(name, options) -> ArgumentParser |
|||
* - name (string): sub-command name |
|||
* - options (object): see [[ArgumentParser.new]] |
|||
* |
|||
* Note: |
|||
* addParser supports an additional aliases option, |
|||
* which allows multiple strings to refer to the same subparser. |
|||
* This example, like svn, aliases co as a shorthand for checkout |
|||
* |
|||
**/ |
|||
ActionSubparsers.prototype.addParser = function (name, options) { |
|||
var parser; |
|||
|
|||
var self = this; |
|||
|
|||
options = options || {}; |
|||
|
|||
options.debug = (this.debug === true); |
|||
|
|||
// set program from the existing prefix
|
|||
if (!options.prog) { |
|||
options.prog = this._progPrefix + ' ' + name; |
|||
} |
|||
|
|||
var aliases = options.aliases || []; |
|||
|
|||
// create a pseudo-action to hold the choice help
|
|||
if (!!options.help || typeof options.help === 'string') { |
|||
var help = options.help; |
|||
delete options.help; |
|||
|
|||
var choiceAction = new ChoicesPseudoAction(name, help); |
|||
this._choicesActions.push(choiceAction); |
|||
} |
|||
|
|||
// create the parser and add it to the map
|
|||
parser = new this._parserClass(options); |
|||
this._nameParserMap[name] = parser; |
|||
|
|||
// make parser available under aliases also
|
|||
aliases.forEach(function (alias) { |
|||
self._nameParserMap[alias] = parser; |
|||
}); |
|||
|
|||
return parser; |
|||
}; |
|||
|
|||
ActionSubparsers.prototype._getSubactions = function () { |
|||
return this._choicesActions; |
|||
}; |
|||
|
|||
/*:nodoc:* |
|||
* ActionSubparsers#call(parser, namespace, values, optionString) -> Void |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Call the action. Parse input aguments |
|||
**/ |
|||
ActionSubparsers.prototype.call = function (parser, namespace, values) { |
|||
var parserName = values[0]; |
|||
var argStrings = values.slice(1); |
|||
|
|||
// set the parser name if requested
|
|||
if (this.dest !== c.SUPPRESS) { |
|||
namespace[this.dest] = parserName; |
|||
} |
|||
|
|||
// select the parser
|
|||
if (this._nameParserMap[parserName]) { |
|||
parser = this._nameParserMap[parserName]; |
|||
} else { |
|||
throw argumentErrorHelper(format( |
|||
'Unknown parser "%s" (choices: [%s]).', |
|||
parserName, |
|||
Object.keys(this._nameParserMap).join(', ') |
|||
)); |
|||
} |
|||
|
|||
// parse all the remaining options into the namespace
|
|||
parser.parseArgs(argStrings, namespace); |
|||
}; |
|||
|
|||
module.exports = ActionSubparsers; |
@ -0,0 +1,47 @@ |
|||
/*:nodoc:* |
|||
* class ActionVersion |
|||
* |
|||
* Support action for printing program version |
|||
* This class inherited from [[Action]] |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var Action = require('../action'); |
|||
|
|||
//
|
|||
// Constants
|
|||
//
|
|||
var c = require('../const'); |
|||
|
|||
/*:nodoc:* |
|||
* new ActionVersion(options) |
|||
* - options (object): options hash see [[Action.new]] |
|||
* |
|||
**/ |
|||
var ActionVersion = module.exports = function ActionVersion(options) { |
|||
options = options || {}; |
|||
options.defaultValue = (options.defaultValue ? options.defaultValue : c.SUPPRESS); |
|||
options.dest = (options.dest || c.SUPPRESS); |
|||
options.nargs = 0; |
|||
this.version = options.version; |
|||
Action.call(this, options); |
|||
}; |
|||
util.inherits(ActionVersion, Action); |
|||
|
|||
/*:nodoc:* |
|||
* ActionVersion#call(parser, namespace, values, optionString) -> Void |
|||
* - parser (ArgumentParser): current parser |
|||
* - namespace (Namespace): namespace for output data |
|||
* - values (Array): parsed values |
|||
* - optionString (Array): input option string(not parsed) |
|||
* |
|||
* Print version and exit |
|||
**/ |
|||
ActionVersion.prototype.call = function (parser) { |
|||
var version = this.version || parser.version; |
|||
var formatter = parser._getFormatter(); |
|||
formatter.addText(version); |
|||
parser.exit(0, formatter.formatHelp()); |
|||
}; |
@ -0,0 +1,482 @@ |
|||
/** internal |
|||
* class ActionContainer |
|||
* |
|||
* Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]] |
|||
**/ |
|||
|
|||
'use strict'; |
|||
|
|||
var format = require('util').format; |
|||
|
|||
// Constants
|
|||
var c = require('./const'); |
|||
|
|||
var $$ = require('./utils'); |
|||
|
|||
//Actions
|
|||
var ActionHelp = require('./action/help'); |
|||
var ActionAppend = require('./action/append'); |
|||
var ActionAppendConstant = require('./action/append/constant'); |
|||
var ActionCount = require('./action/count'); |
|||
var ActionStore = require('./action/store'); |
|||
var ActionStoreConstant = require('./action/store/constant'); |
|||
var ActionStoreTrue = require('./action/store/true'); |
|||
var ActionStoreFalse = require('./action/store/false'); |
|||
var ActionVersion = require('./action/version'); |
|||
var ActionSubparsers = require('./action/subparsers'); |
|||
|
|||
// Errors
|
|||
var argumentErrorHelper = require('./argument/error'); |
|||
|
|||
/** |
|||
* new ActionContainer(options) |
|||
* |
|||
* Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]] |
|||
* |
|||
* ##### Options: |
|||
* |
|||
* - `description` -- A description of what the program does |
|||
* - `prefixChars` -- Characters that prefix optional arguments |
|||
* - `argumentDefault` -- The default value for all arguments |
|||
* - `conflictHandler` -- The conflict handler to use for duplicate arguments |
|||
**/ |
|||
var ActionContainer = module.exports = function ActionContainer(options) { |
|||
options = options || {}; |
|||
|
|||
this.description = options.description; |
|||
this.argumentDefault = options.argumentDefault; |
|||
this.prefixChars = options.prefixChars || ''; |
|||
this.conflictHandler = options.conflictHandler; |
|||
|
|||
// set up registries
|
|||
this._registries = {}; |
|||
|
|||
// register actions
|
|||
this.register('action', null, ActionStore); |
|||
this.register('action', 'store', ActionStore); |
|||
this.register('action', 'storeConst', ActionStoreConstant); |
|||
this.register('action', 'storeTrue', ActionStoreTrue); |
|||
this.register('action', 'storeFalse', ActionStoreFalse); |
|||
this.register('action', 'append', ActionAppend); |
|||
this.register('action', 'appendConst', ActionAppendConstant); |
|||
this.register('action', 'count', ActionCount); |
|||
this.register('action', 'help', ActionHelp); |
|||
this.register('action', 'version', ActionVersion); |
|||
this.register('action', 'parsers', ActionSubparsers); |
|||
|
|||
// raise an exception if the conflict handler is invalid
|
|||
this._getHandler(); |
|||
|
|||
// action storage
|
|||
this._actions = []; |
|||
this._optionStringActions = {}; |
|||
|
|||
// groups
|
|||
this._actionGroups = []; |
|||
this._mutuallyExclusiveGroups = []; |
|||
|
|||
// defaults storage
|
|||
this._defaults = {}; |
|||
|
|||
// determines whether an "option" looks like a negative number
|
|||
// -1, -1.5 -5e+4
|
|||
this._regexpNegativeNumber = new RegExp('^[-]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$'); |
|||
|
|||
// whether or not there are any optionals that look like negative
|
|||
// numbers -- uses a list so it can be shared and edited
|
|||
this._hasNegativeNumberOptionals = []; |
|||
}; |
|||
|
|||
// Groups must be required, then ActionContainer already defined
|
|||
var ArgumentGroup = require('./argument/group'); |
|||
var MutuallyExclusiveGroup = require('./argument/exclusive'); |
|||
|
|||
//
|
|||
// Registration methods
|
|||
//
|
|||
|
|||
/** |
|||
* ActionContainer#register(registryName, value, object) -> Void |
|||
* - registryName (String) : object type action|type |
|||
* - value (string) : keyword |
|||
* - object (Object|Function) : handler |
|||
* |
|||
* Register handlers |
|||
**/ |
|||
ActionContainer.prototype.register = function (registryName, value, object) { |
|||
this._registries[registryName] = this._registries[registryName] || {}; |
|||
this._registries[registryName][value] = object; |
|||
}; |
|||
|
|||
ActionContainer.prototype._registryGet = function (registryName, value, defaultValue) { |
|||
if (arguments.length < 3) { |
|||
defaultValue = null; |
|||
} |
|||
return this._registries[registryName][value] || defaultValue; |
|||
}; |
|||
|
|||
//
|
|||
// Namespace default accessor methods
|
|||
//
|
|||
|
|||
/** |
|||
* ActionContainer#setDefaults(options) -> Void |
|||
* - options (object):hash of options see [[Action.new]] |
|||
* |
|||
* Set defaults |
|||
**/ |
|||
ActionContainer.prototype.setDefaults = function (options) { |
|||
options = options || {}; |
|||
for (var property in options) { |
|||
if ($$.has(options, property)) { |
|||
this._defaults[property] = options[property]; |
|||
} |
|||
} |
|||
|
|||
// if these defaults match any existing arguments, replace the previous
|
|||
// default on the object with the new one
|
|||
this._actions.forEach(function (action) { |
|||
if ($$.has(options, action.dest)) { |
|||
action.defaultValue = options[action.dest]; |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
/** |
|||
* ActionContainer#getDefault(dest) -> Mixed |
|||
* - dest (string): action destination |
|||
* |
|||
* Return action default value |
|||
**/ |
|||
ActionContainer.prototype.getDefault = function (dest) { |
|||
var result = $$.has(this._defaults, dest) ? this._defaults[dest] : null; |
|||
|
|||
this._actions.forEach(function (action) { |
|||
if (action.dest === dest && $$.has(action, 'defaultValue')) { |
|||
result = action.defaultValue; |
|||
} |
|||
}); |
|||
|
|||
return result; |
|||
}; |
|||
//
|
|||
// Adding argument actions
|
|||
//
|
|||
|
|||
/** |
|||
* ActionContainer#addArgument(args, options) -> Object |
|||
* - args (String|Array): argument key, or array of argument keys |
|||
* - options (Object): action objects see [[Action.new]] |
|||
* |
|||
* #### Examples |
|||
* - addArgument([ '-f', '--foo' ], { action: 'store', defaultValue: 1, ... }) |
|||
* - addArgument([ 'bar' ], { action: 'store', nargs: 1, ... }) |
|||
* - addArgument('--baz', { action: 'store', nargs: 1, ... }) |
|||
**/ |
|||
ActionContainer.prototype.addArgument = function (args, options) { |
|||
args = args; |
|||
options = options || {}; |
|||
|
|||
if (typeof args === 'string') { |
|||
args = [ args ]; |
|||
} |
|||
if (!Array.isArray(args)) { |
|||
throw new TypeError('addArgument first argument should be a string or an array'); |
|||
} |
|||
if (typeof options !== 'object' || Array.isArray(options)) { |
|||
throw new TypeError('addArgument second argument should be a hash'); |
|||
} |
|||
|
|||
// if no positional args are supplied or only one is supplied and
|
|||
// it doesn't look like an option string, parse a positional argument
|
|||
if (!args || args.length === 1 && this.prefixChars.indexOf(args[0][0]) < 0) { |
|||
if (args && !!options.dest) { |
|||
throw new Error('dest supplied twice for positional argument'); |
|||
} |
|||
options = this._getPositional(args, options); |
|||
|
|||
// otherwise, we're adding an optional argument
|
|||
} else { |
|||
options = this._getOptional(args, options); |
|||
} |
|||
|
|||
// if no default was supplied, use the parser-level default
|
|||
if (typeof options.defaultValue === 'undefined') { |
|||
var dest = options.dest; |
|||
if ($$.has(this._defaults, dest)) { |
|||
options.defaultValue = this._defaults[dest]; |
|||
} else if (typeof this.argumentDefault !== 'undefined') { |
|||
options.defaultValue = this.argumentDefault; |
|||
} |
|||
} |
|||
|
|||
// create the action object, and add it to the parser
|
|||
var ActionClass = this._popActionClass(options); |
|||
if (typeof ActionClass !== 'function') { |
|||
throw new Error(format('Unknown action "%s".', ActionClass)); |
|||
} |
|||
var action = new ActionClass(options); |
|||
|
|||
// throw an error if the action type is not callable
|
|||
var typeFunction = this._registryGet('type', action.type, action.type); |
|||
if (typeof typeFunction !== 'function') { |
|||
throw new Error(format('"%s" is not callable', typeFunction)); |
|||
} |
|||
|
|||
return this._addAction(action); |
|||
}; |
|||
|
|||
/** |
|||
* ActionContainer#addArgumentGroup(options) -> ArgumentGroup |
|||
* - options (Object): hash of options see [[ArgumentGroup.new]] |
|||
* |
|||
* Create new arguments groups |
|||
**/ |
|||
ActionContainer.prototype.addArgumentGroup = function (options) { |
|||
var group = new ArgumentGroup(this, options); |
|||
this._actionGroups.push(group); |
|||
return group; |
|||
}; |
|||
|
|||
/** |
|||
* ActionContainer#addMutuallyExclusiveGroup(options) -> ArgumentGroup |
|||
* - options (Object): {required: false} |
|||
* |
|||
* Create new mutual exclusive groups |
|||
**/ |
|||
ActionContainer.prototype.addMutuallyExclusiveGroup = function (options) { |
|||
var group = new MutuallyExclusiveGroup(this, options); |
|||
this._mutuallyExclusiveGroups.push(group); |
|||
return group; |
|||
}; |
|||
|
|||
ActionContainer.prototype._addAction = function (action) { |
|||
var self = this; |
|||
|
|||
// resolve any conflicts
|
|||
this._checkConflict(action); |
|||
|
|||
// add to actions list
|
|||
this._actions.push(action); |
|||
action.container = this; |
|||
|
|||
// index the action by any option strings it has
|
|||
action.optionStrings.forEach(function (optionString) { |
|||
self._optionStringActions[optionString] = action; |
|||
}); |
|||
|
|||
// set the flag if any option strings look like negative numbers
|
|||
action.optionStrings.forEach(function (optionString) { |
|||
if (optionString.match(self._regexpNegativeNumber)) { |
|||
if (!self._hasNegativeNumberOptionals.some(Boolean)) { |
|||
self._hasNegativeNumberOptionals.push(true); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
// return the created action
|
|||
return action; |
|||
}; |
|||
|
|||
ActionContainer.prototype._removeAction = function (action) { |
|||
var actionIndex = this._actions.indexOf(action); |
|||
if (actionIndex >= 0) { |
|||
this._actions.splice(actionIndex, 1); |
|||
} |
|||
}; |
|||
|
|||
ActionContainer.prototype._addContainerActions = function (container) { |
|||
// collect groups by titles
|
|||
var titleGroupMap = {}; |
|||
this._actionGroups.forEach(function (group) { |
|||
if (titleGroupMap[group.title]) { |
|||
throw new Error(format('Cannot merge actions - two groups are named "%s".', group.title)); |
|||
} |
|||
titleGroupMap[group.title] = group; |
|||
}); |
|||
|
|||
// map each action to its group
|
|||
var groupMap = {}; |
|||
function actionHash(action) { |
|||
// unique (hopefully?) string suitable as dictionary key
|
|||
return action.getName(); |
|||
} |
|||
container._actionGroups.forEach(function (group) { |
|||
// if a group with the title exists, use that, otherwise
|
|||
// create a new group matching the container's group
|
|||
if (!titleGroupMap[group.title]) { |
|||
titleGroupMap[group.title] = this.addArgumentGroup({ |
|||
title: group.title, |
|||
description: group.description |
|||
}); |
|||
} |
|||
|
|||
// map the actions to their new group
|
|||
group._groupActions.forEach(function (action) { |
|||
groupMap[actionHash(action)] = titleGroupMap[group.title]; |
|||
}); |
|||
}, this); |
|||
|
|||
// add container's mutually exclusive groups
|
|||
// NOTE: if add_mutually_exclusive_group ever gains title= and
|
|||
// description= then this code will need to be expanded as above
|
|||
var mutexGroup; |
|||
container._mutuallyExclusiveGroups.forEach(function (group) { |
|||
mutexGroup = this.addMutuallyExclusiveGroup({ |
|||
required: group.required |
|||
}); |
|||
// map the actions to their new mutex group
|
|||
group._groupActions.forEach(function (action) { |
|||
groupMap[actionHash(action)] = mutexGroup; |
|||
}); |
|||
}, this); // forEach takes a 'this' argument
|
|||
|
|||
// add all actions to this container or their group
|
|||
container._actions.forEach(function (action) { |
|||
var key = actionHash(action); |
|||
if (groupMap[key]) { |
|||
groupMap[key]._addAction(action); |
|||
} else { |
|||
this._addAction(action); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
ActionContainer.prototype._getPositional = function (dest, options) { |
|||
if (Array.isArray(dest)) { |
|||
dest = dest[0]; |
|||
} |
|||
// make sure required is not specified
|
|||
if (options.required) { |
|||
throw new Error('"required" is an invalid argument for positionals.'); |
|||
} |
|||
|
|||
// mark positional arguments as required if at least one is
|
|||
// always required
|
|||
if (options.nargs !== c.OPTIONAL && options.nargs !== c.ZERO_OR_MORE) { |
|||
options.required = true; |
|||
} |
|||
if (options.nargs === c.ZERO_OR_MORE && typeof options.defaultValue === 'undefined') { |
|||
options.required = true; |
|||
} |
|||
|
|||
// return the keyword arguments with no option strings
|
|||
options.dest = dest; |
|||
options.optionStrings = []; |
|||
return options; |
|||
}; |
|||
|
|||
ActionContainer.prototype._getOptional = function (args, options) { |
|||
var prefixChars = this.prefixChars; |
|||
var optionStrings = []; |
|||
var optionStringsLong = []; |
|||
|
|||
// determine short and long option strings
|
|||
args.forEach(function (optionString) { |
|||
// error on strings that don't start with an appropriate prefix
|
|||
if (prefixChars.indexOf(optionString[0]) < 0) { |
|||
throw new Error(format('Invalid option string "%s": must start with a "%s".', |
|||
optionString, |
|||
prefixChars |
|||
)); |
|||
} |
|||
|
|||
// strings starting with two prefix characters are long options
|
|||
optionStrings.push(optionString); |
|||
if (optionString.length > 1 && prefixChars.indexOf(optionString[1]) >= 0) { |
|||
optionStringsLong.push(optionString); |
|||
} |
|||
}); |
|||
|
|||
// infer dest, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
|
|||
var dest = options.dest || null; |
|||
delete options.dest; |
|||
|
|||
if (!dest) { |
|||
var optionStringDest = optionStringsLong.length ? optionStringsLong[0] : optionStrings[0]; |
|||
dest = $$.trimChars(optionStringDest, this.prefixChars); |
|||
|
|||
if (dest.length === 0) { |
|||
throw new Error( |
|||
format('dest= is required for options like "%s"', optionStrings.join(', ')) |
|||
); |
|||
} |
|||
dest = dest.replace(/-/g, '_'); |
|||
} |
|||
|
|||
// return the updated keyword arguments
|
|||
options.dest = dest; |
|||
options.optionStrings = optionStrings; |
|||
|
|||
return options; |
|||
}; |
|||
|
|||
ActionContainer.prototype._popActionClass = function (options, defaultValue) { |
|||
defaultValue = defaultValue || null; |
|||
|
|||
var action = (options.action || defaultValue); |
|||
delete options.action; |
|||
|
|||
var actionClass = this._registryGet('action', action, action); |
|||
return actionClass; |
|||
}; |
|||
|
|||
ActionContainer.prototype._getHandler = function () { |
|||
var handlerString = this.conflictHandler; |
|||
var handlerFuncName = '_handleConflict' + $$.capitalize(handlerString); |
|||
var func = this[handlerFuncName]; |
|||
if (typeof func === 'undefined') { |
|||
var msg = 'invalid conflict resolution value: ' + handlerString; |
|||
throw new Error(msg); |
|||
} else { |
|||
return func; |
|||
} |
|||
}; |
|||
|
|||
ActionContainer.prototype._checkConflict = function (action) { |
|||
var optionStringActions = this._optionStringActions; |
|||
var conflictOptionals = []; |
|||
|
|||
// find all options that conflict with this option
|
|||
// collect pairs, the string, and an existing action that it conflicts with
|
|||
action.optionStrings.forEach(function (optionString) { |
|||
var conflOptional = optionStringActions[optionString]; |
|||
if (typeof conflOptional !== 'undefined') { |
|||
conflictOptionals.push([ optionString, conflOptional ]); |
|||
} |
|||
}); |
|||
|
|||
if (conflictOptionals.length > 0) { |
|||
var conflictHandler = this._getHandler(); |
|||
conflictHandler.call(this, action, conflictOptionals); |
|||
} |
|||
}; |
|||
|
|||
ActionContainer.prototype._handleConflictError = function (action, conflOptionals) { |
|||
var conflicts = conflOptionals.map(function (pair) { return pair[0]; }); |
|||
conflicts = conflicts.join(', '); |
|||
throw argumentErrorHelper( |
|||
action, |
|||
format('Conflicting option string(s): %s', conflicts) |
|||
); |
|||
}; |
|||
|
|||
ActionContainer.prototype._handleConflictResolve = function (action, conflOptionals) { |
|||
// remove all conflicting options
|
|||
var self = this; |
|||
conflOptionals.forEach(function (pair) { |
|||
var optionString = pair[0]; |
|||
var conflictingAction = pair[1]; |
|||
// remove the conflicting option string
|
|||
var i = conflictingAction.optionStrings.indexOf(optionString); |
|||
if (i >= 0) { |
|||
conflictingAction.optionStrings.splice(i, 1); |
|||
} |
|||
delete self._optionStringActions[optionString]; |
|||
// if the option now has no option string, remove it from the
|
|||
// container holding it
|
|||
if (conflictingAction.optionStrings.length === 0) { |
|||
conflictingAction.container._removeAction(conflictingAction); |
|||
} |
|||
}); |
|||
}; |
@ -0,0 +1,14 @@ |
|||
'use strict'; |
|||
|
|||
module.exports.ArgumentParser = require('./argument_parser.js'); |
|||
module.exports.Namespace = require('./namespace'); |
|||
module.exports.Action = require('./action'); |
|||
module.exports.HelpFormatter = require('./help/formatter.js'); |
|||
module.exports.Const = require('./const.js'); |
|||
|
|||
module.exports.ArgumentDefaultsHelpFormatter = |
|||
require('./help/added_formatters.js').ArgumentDefaultsHelpFormatter; |
|||
module.exports.RawDescriptionHelpFormatter = |
|||
require('./help/added_formatters.js').RawDescriptionHelpFormatter; |
|||
module.exports.RawTextHelpFormatter = |
|||
require('./help/added_formatters.js').RawTextHelpFormatter; |
@ -0,0 +1,50 @@ |
|||
'use strict'; |
|||
|
|||
|
|||
var format = require('util').format; |
|||
|
|||
|
|||
var ERR_CODE = 'ARGError'; |
|||
|
|||
/*:nodoc:* |
|||
* argumentError(argument, message) -> TypeError |
|||
* - argument (Object): action with broken argument |
|||
* - message (String): error message |
|||
* |
|||
* Error format helper. An error from creating or using an argument |
|||
* (optional or positional). The string value of this exception |
|||
* is the message, augmented with information |
|||
* about the argument that caused it. |
|||
* |
|||
* #####Example |
|||
* |
|||
* var argumentErrorHelper = require('./argument/error'); |
|||
* if (conflictOptionals.length > 0) { |
|||
* throw argumentErrorHelper( |
|||
* action, |
|||
* format('Conflicting option string(s): %s', conflictOptionals.join(', ')) |
|||
* ); |
|||
* } |
|||
* |
|||
**/ |
|||
module.exports = function (argument, message) { |
|||
var argumentName = null; |
|||
var errMessage; |
|||
var err; |
|||
|
|||
if (argument.getName) { |
|||
argumentName = argument.getName(); |
|||
} else { |
|||
argumentName = '' + argument; |
|||
} |
|||
|
|||
if (!argumentName) { |
|||
errMessage = message; |
|||
} else { |
|||
errMessage = format('argument "%s": %s', argumentName, message); |
|||
} |
|||
|
|||
err = new TypeError(errMessage); |
|||
err.code = ERR_CODE; |
|||
return err; |
|||
}; |
@ -0,0 +1,54 @@ |
|||
/** internal |
|||
* class MutuallyExclusiveGroup |
|||
* |
|||
* Group arguments. |
|||
* By default, ArgumentParser groups command-line arguments |
|||
* into “positional arguments” and “optional arguments” |
|||
* when displaying help messages. When there is a better |
|||
* conceptual grouping of arguments than this default one, |
|||
* appropriate groups can be created using the addArgumentGroup() method |
|||
* |
|||
* This class inherited from [[ArgumentContainer]] |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var ArgumentGroup = require('./group'); |
|||
|
|||
/** |
|||
* new MutuallyExclusiveGroup(container, options) |
|||
* - container (object): main container |
|||
* - options (object): options.required -> true/false |
|||
* |
|||
* `required` could be an argument itself, but making it a property of |
|||
* the options argument is more consistent with the JS adaptation of the Python) |
|||
**/ |
|||
var MutuallyExclusiveGroup = module.exports = function MutuallyExclusiveGroup(container, options) { |
|||
var required; |
|||
options = options || {}; |
|||
required = options.required || false; |
|||
ArgumentGroup.call(this, container); |
|||
this.required = required; |
|||
|
|||
}; |
|||
util.inherits(MutuallyExclusiveGroup, ArgumentGroup); |
|||
|
|||
|
|||
MutuallyExclusiveGroup.prototype._addAction = function (action) { |
|||
var msg; |
|||
if (action.required) { |
|||
msg = 'mutually exclusive arguments must be optional'; |
|||
throw new Error(msg); |
|||
} |
|||
action = this._container._addAction(action); |
|||
this._groupActions.push(action); |
|||
return action; |
|||
}; |
|||
|
|||
|
|||
MutuallyExclusiveGroup.prototype._removeAction = function (action) { |
|||
this._container._removeAction(action); |
|||
this._groupActions.remove(action); |
|||
}; |
|||
|
@ -0,0 +1,75 @@ |
|||
/** internal |
|||
* class ArgumentGroup |
|||
* |
|||
* Group arguments. |
|||
* By default, ArgumentParser groups command-line arguments |
|||
* into “positional arguments” and “optional arguments” |
|||
* when displaying help messages. When there is a better |
|||
* conceptual grouping of arguments than this default one, |
|||
* appropriate groups can be created using the addArgumentGroup() method |
|||
* |
|||
* This class inherited from [[ArgumentContainer]] |
|||
**/ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
var ActionContainer = require('../action_container'); |
|||
|
|||
|
|||
/** |
|||
* new ArgumentGroup(container, options) |
|||
* - container (object): main container |
|||
* - options (object): hash of group options |
|||
* |
|||
* #### options |
|||
* - **prefixChars** group name prefix |
|||
* - **argumentDefault** default argument value |
|||
* - **title** group title |
|||
* - **description** group description |
|||
* |
|||
**/ |
|||
var ArgumentGroup = module.exports = function ArgumentGroup(container, options) { |
|||
|
|||
options = options || {}; |
|||
|
|||
// add any missing keyword arguments by checking the container
|
|||
options.conflictHandler = (options.conflictHandler || container.conflictHandler); |
|||
options.prefixChars = (options.prefixChars || container.prefixChars); |
|||
options.argumentDefault = (options.argumentDefault || container.argumentDefault); |
|||
|
|||
ActionContainer.call(this, options); |
|||
|
|||
// group attributes
|
|||
this.title = options.title; |
|||
this._groupActions = []; |
|||
|
|||
// share most attributes with the container
|
|||
this._container = container; |
|||
this._registries = container._registries; |
|||
this._actions = container._actions; |
|||
this._optionStringActions = container._optionStringActions; |
|||
this._defaults = container._defaults; |
|||
this._hasNegativeNumberOptionals = container._hasNegativeNumberOptionals; |
|||
this._mutuallyExclusiveGroups = container._mutuallyExclusiveGroups; |
|||
}; |
|||
util.inherits(ArgumentGroup, ActionContainer); |
|||
|
|||
|
|||
ArgumentGroup.prototype._addAction = function (action) { |
|||
// Parent add action
|
|||
action = ActionContainer.prototype._addAction.call(this, action); |
|||
this._groupActions.push(action); |
|||
return action; |
|||
}; |
|||
|
|||
|
|||
ArgumentGroup.prototype._removeAction = function (action) { |
|||
// Parent remove action
|
|||
ActionContainer.prototype._removeAction.call(this, action); |
|||
var actionIndex = this._groupActions.indexOf(action); |
|||
if (actionIndex >= 0) { |
|||
this._groupActions.splice(actionIndex, 1); |
|||
} |
|||
}; |
|||
|
1161
chatto/src/main/javascript/node_modules/argparse/lib/argument_parser.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,21 @@ |
|||
//
|
|||
// Constants
|
|||
//
|
|||
|
|||
'use strict'; |
|||
|
|||
module.exports.EOL = '\n'; |
|||
|
|||
module.exports.SUPPRESS = '==SUPPRESS=='; |
|||
|
|||
module.exports.OPTIONAL = '?'; |
|||
|
|||
module.exports.ZERO_OR_MORE = '*'; |
|||
|
|||
module.exports.ONE_OR_MORE = '+'; |
|||
|
|||
module.exports.PARSER = 'A...'; |
|||
|
|||
module.exports.REMAINDER = '...'; |
|||
|
|||
module.exports._UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'; |
@ -0,0 +1,87 @@ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
|
|||
// Constants
|
|||
var c = require('../const'); |
|||
|
|||
var $$ = require('../utils'); |
|||
var HelpFormatter = require('./formatter.js'); |
|||
|
|||
/** |
|||
* new RawDescriptionHelpFormatter(options) |
|||
* new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...}) |
|||
* |
|||
* Help message formatter which adds default values to argument help. |
|||
* |
|||
* Only the name of this class is considered a public API. All the methods |
|||
* provided by the class are considered an implementation detail. |
|||
**/ |
|||
|
|||
function ArgumentDefaultsHelpFormatter(options) { |
|||
HelpFormatter.call(this, options); |
|||
} |
|||
|
|||
util.inherits(ArgumentDefaultsHelpFormatter, HelpFormatter); |
|||
|
|||
ArgumentDefaultsHelpFormatter.prototype._getHelpString = function (action) { |
|||
var help = action.help; |
|||
if (action.help.indexOf('%(defaultValue)s') === -1) { |
|||
if (action.defaultValue !== c.SUPPRESS) { |
|||
var defaulting_nargs = [ c.OPTIONAL, c.ZERO_OR_MORE ]; |
|||
if (action.isOptional() || (defaulting_nargs.indexOf(action.nargs) >= 0)) { |
|||
help += ' (default: %(defaultValue)s)'; |
|||
} |
|||
} |
|||
} |
|||
return help; |
|||
}; |
|||
|
|||
module.exports.ArgumentDefaultsHelpFormatter = ArgumentDefaultsHelpFormatter; |
|||
|
|||
/** |
|||
* new RawDescriptionHelpFormatter(options) |
|||
* new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...}) |
|||
* |
|||
* Help message formatter which retains any formatting in descriptions. |
|||
* |
|||
* Only the name of this class is considered a public API. All the methods |
|||
* provided by the class are considered an implementation detail. |
|||
**/ |
|||
|
|||
function RawDescriptionHelpFormatter(options) { |
|||
HelpFormatter.call(this, options); |
|||
} |
|||
|
|||
util.inherits(RawDescriptionHelpFormatter, HelpFormatter); |
|||
|
|||
RawDescriptionHelpFormatter.prototype._fillText = function (text, width, indent) { |
|||
var lines = text.split('\n'); |
|||
lines = lines.map(function (line) { |
|||
return $$.trimEnd(indent + line); |
|||
}); |
|||
return lines.join('\n'); |
|||
}; |
|||
module.exports.RawDescriptionHelpFormatter = RawDescriptionHelpFormatter; |
|||
|
|||
/** |
|||
* new RawTextHelpFormatter(options) |
|||
* new ArgumentParser({formatterClass: argparse.RawTextHelpFormatter, ...}) |
|||
* |
|||
* Help message formatter which retains formatting of all help text. |
|||
* |
|||
* Only the name of this class is considered a public API. All the methods |
|||
* provided by the class are considered an implementation detail. |
|||
**/ |
|||
|
|||
function RawTextHelpFormatter(options) { |
|||
RawDescriptionHelpFormatter.call(this, options); |
|||
} |
|||
|
|||
util.inherits(RawTextHelpFormatter, RawDescriptionHelpFormatter); |
|||
|
|||
RawTextHelpFormatter.prototype._splitLines = function (text) { |
|||
return text.split('\n'); |
|||
}; |
|||
|
|||
module.exports.RawTextHelpFormatter = RawTextHelpFormatter; |
@ -0,0 +1,795 @@ |
|||
/** |
|||
* class HelpFormatter |
|||
* |
|||
* Formatter for generating usage messages and argument help strings. Only the |
|||
* name of this class is considered a public API. All the methods provided by |
|||
* the class are considered an implementation detail. |
|||
* |
|||
* Do not call in your code, use this class only for inherits your own forvatter |
|||
* |
|||
* ToDo add [additonal formatters][1] |
|||
* |
|||
* [1]:http://docs.python.org/dev/library/argparse.html#formatter-class
|
|||
**/ |
|||
'use strict'; |
|||
|
|||
var sprintf = require('sprintf-js').sprintf; |
|||
|
|||
// Constants
|
|||
var c = require('../const'); |
|||
|
|||
var $$ = require('../utils'); |
|||
|
|||
|
|||
/*:nodoc:* internal |
|||
* new Support(parent, heding) |
|||
* - parent (object): parent section |
|||
* - heading (string): header string |
|||
* |
|||
**/ |
|||
function Section(parent, heading) { |
|||
this._parent = parent; |
|||
this._heading = heading; |
|||
this._items = []; |
|||
} |
|||
|
|||
/*:nodoc:* internal |
|||
* Section#addItem(callback) -> Void |
|||
* - callback (array): tuple with function and args |
|||
* |
|||
* Add function for single element |
|||
**/ |
|||
Section.prototype.addItem = function (callback) { |
|||
this._items.push(callback); |
|||
}; |
|||
|
|||
/*:nodoc:* internal |
|||
* Section#formatHelp(formatter) -> string |
|||
* - formatter (HelpFormatter): current formatter |
|||
* |
|||
* Form help section string |
|||
* |
|||
**/ |
|||
Section.prototype.formatHelp = function (formatter) { |
|||
var itemHelp, heading; |
|||
|
|||
// format the indented section
|
|||
if (this._parent) { |
|||
formatter._indent(); |
|||
} |
|||
|
|||
itemHelp = this._items.map(function (item) { |
|||
var obj, func, args; |
|||
|
|||
obj = formatter; |
|||
func = item[0]; |
|||
args = item[1]; |
|||
return func.apply(obj, args); |
|||
}); |
|||
itemHelp = formatter._joinParts(itemHelp); |
|||
|
|||
if (this._parent) { |
|||
formatter._dedent(); |
|||
} |
|||
|
|||
// return nothing if the section was empty
|
|||
if (!itemHelp) { |
|||
return ''; |
|||
} |
|||
|
|||
// add the heading if the section was non-empty
|
|||
heading = ''; |
|||
if (this._heading && this._heading !== c.SUPPRESS) { |
|||
var currentIndent = formatter.currentIndent; |
|||
heading = $$.repeat(' ', currentIndent) + this._heading + ':' + c.EOL; |
|||
} |
|||
|
|||
// join the section-initialize newline, the heading and the help
|
|||
return formatter._joinParts([ c.EOL, heading, itemHelp, c.EOL ]); |
|||
}; |
|||
|
|||
/** |
|||
* new HelpFormatter(options) |
|||
* |
|||
* #### Options: |
|||
* - `prog`: program name |
|||
* - `indentIncriment`: indent step, default value 2 |
|||
* - `maxHelpPosition`: max help position, default value = 24 |
|||
* - `width`: line width |
|||
* |
|||
**/ |
|||
var HelpFormatter = module.exports = function HelpFormatter(options) { |
|||
options = options || {}; |
|||
|
|||
this._prog = options.prog; |
|||
|
|||
this._maxHelpPosition = options.maxHelpPosition || 24; |
|||
this._width = (options.width || ((process.env.COLUMNS || 80) - 2)); |
|||
|
|||
this._currentIndent = 0; |
|||
this._indentIncriment = options.indentIncriment || 2; |
|||
this._level = 0; |
|||
this._actionMaxLength = 0; |
|||
|
|||
this._rootSection = new Section(null); |
|||
this._currentSection = this._rootSection; |
|||
|
|||
this._whitespaceMatcher = new RegExp('\\s+', 'g'); |
|||
this._longBreakMatcher = new RegExp(c.EOL + c.EOL + c.EOL + '+', 'g'); |
|||
}; |
|||
|
|||
HelpFormatter.prototype._indent = function () { |
|||
this._currentIndent += this._indentIncriment; |
|||
this._level += 1; |
|||
}; |
|||
|
|||
HelpFormatter.prototype._dedent = function () { |
|||
this._currentIndent -= this._indentIncriment; |
|||
this._level -= 1; |
|||
if (this._currentIndent < 0) { |
|||
throw new Error('Indent decreased below 0.'); |
|||
} |
|||
}; |
|||
|
|||
HelpFormatter.prototype._addItem = function (func, args) { |
|||
this._currentSection.addItem([ func, args ]); |
|||
}; |
|||
|
|||
//
|
|||
// Message building methods
|
|||
//
|
|||
|
|||
/** |
|||
* HelpFormatter#startSection(heading) -> Void |
|||
* - heading (string): header string |
|||
* |
|||
* Start new help section |
|||
* |
|||
* See alse [code example][1] |
|||
* |
|||
* ##### Example |
|||
* |
|||
* formatter.startSection(actionGroup.title); |
|||
* formatter.addText(actionGroup.description); |
|||
* formatter.addArguments(actionGroup._groupActions); |
|||
* formatter.endSection(); |
|||
* |
|||
**/ |
|||
HelpFormatter.prototype.startSection = function (heading) { |
|||
this._indent(); |
|||
var section = new Section(this._currentSection, heading); |
|||
var func = section.formatHelp.bind(section); |
|||
this._addItem(func, [ this ]); |
|||
this._currentSection = section; |
|||
}; |
|||
|
|||
/** |
|||
* HelpFormatter#endSection -> Void |
|||
* |
|||
* End help section |
|||
* |
|||
* ##### Example |
|||
* |
|||
* formatter.startSection(actionGroup.title); |
|||
* formatter.addText(actionGroup.description); |
|||
* formatter.addArguments(actionGroup._groupActions); |
|||
* formatter.endSection(); |
|||
**/ |
|||
HelpFormatter.prototype.endSection = function () { |
|||
this._currentSection = this._currentSection._parent; |
|||
this._dedent(); |
|||
}; |
|||
|
|||
/** |
|||
* HelpFormatter#addText(text) -> Void |
|||
* - text (string): plain text |
|||
* |
|||
* Add plain text into current section |
|||
* |
|||
* ##### Example |
|||
* |
|||
* formatter.startSection(actionGroup.title); |
|||
* formatter.addText(actionGroup.description); |
|||
* formatter.addArguments(actionGroup._groupActions); |
|||
* formatter.endSection(); |
|||
* |
|||
**/ |
|||
HelpFormatter.prototype.addText = function (text) { |
|||
if (text && text !== c.SUPPRESS) { |
|||
this._addItem(this._formatText, [ text ]); |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* HelpFormatter#addUsage(usage, actions, groups, prefix) -> Void |
|||
* - usage (string): usage text |
|||
* - actions (array): actions list |
|||
* - groups (array): groups list |
|||
* - prefix (string): usage prefix |
|||
* |
|||
* Add usage data into current section |
|||
* |
|||
* ##### Example |
|||
* |
|||
* formatter.addUsage(this.usage, this._actions, []); |
|||
* return formatter.formatHelp(); |
|||
* |
|||
**/ |
|||
HelpFormatter.prototype.addUsage = function (usage, actions, groups, prefix) { |
|||
if (usage !== c.SUPPRESS) { |
|||
this._addItem(this._formatUsage, [ usage, actions, groups, prefix ]); |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* HelpFormatter#addArgument(action) -> Void |
|||
* - action (object): action |
|||
* |
|||
* Add argument into current section |
|||
* |
|||
* Single variant of [[HelpFormatter#addArguments]] |
|||
**/ |
|||
HelpFormatter.prototype.addArgument = function (action) { |
|||
if (action.help !== c.SUPPRESS) { |
|||
var self = this; |
|||
|
|||
// find all invocations
|
|||
var invocations = [ this._formatActionInvocation(action) ]; |
|||
var invocationLength = invocations[0].length; |
|||
|
|||
var actionLength; |
|||
|
|||
if (action._getSubactions) { |
|||
this._indent(); |
|||
action._getSubactions().forEach(function (subaction) { |
|||
|
|||
var invocationNew = self._formatActionInvocation(subaction); |
|||
invocations.push(invocationNew); |
|||
invocationLength = Math.max(invocationLength, invocationNew.length); |
|||
|
|||
}); |
|||
this._dedent(); |
|||
} |
|||
|
|||
// update the maximum item length
|
|||
actionLength = invocationLength + this._currentIndent; |
|||
this._actionMaxLength = Math.max(this._actionMaxLength, actionLength); |
|||
|
|||
// add the item to the list
|
|||
this._addItem(this._formatAction, [ action ]); |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* HelpFormatter#addArguments(actions) -> Void |
|||
* - actions (array): actions list |
|||
* |
|||
* Mass add arguments into current section |
|||
* |
|||
* ##### Example |
|||
* |
|||
* formatter.startSection(actionGroup.title); |
|||
* formatter.addText(actionGroup.description); |
|||
* formatter.addArguments(actionGroup._groupActions); |
|||
* formatter.endSection(); |
|||
* |
|||
**/ |
|||
HelpFormatter.prototype.addArguments = function (actions) { |
|||
var self = this; |
|||
actions.forEach(function (action) { |
|||
self.addArgument(action); |
|||
}); |
|||
}; |
|||
|
|||
//
|
|||
// Help-formatting methods
|
|||
//
|
|||
|
|||
/** |
|||
* HelpFormatter#formatHelp -> string |
|||
* |
|||
* Format help |
|||
* |
|||
* ##### Example |
|||
* |
|||
* formatter.addText(this.epilog); |
|||
* return formatter.formatHelp(); |
|||
* |
|||
**/ |
|||
HelpFormatter.prototype.formatHelp = function () { |
|||
var help = this._rootSection.formatHelp(this); |
|||
if (help) { |
|||
help = help.replace(this._longBreakMatcher, c.EOL + c.EOL); |
|||
help = $$.trimChars(help, c.EOL) + c.EOL; |
|||
} |
|||
return help; |
|||
}; |
|||
|
|||
HelpFormatter.prototype._joinParts = function (partStrings) { |
|||
return partStrings.filter(function (part) { |
|||
return (part && part !== c.SUPPRESS); |
|||
}).join(''); |
|||
}; |
|||
|
|||
HelpFormatter.prototype._formatUsage = function (usage, actions, groups, prefix) { |
|||
if (!prefix && typeof prefix !== 'string') { |
|||
prefix = 'usage: '; |
|||
} |
|||
|
|||
actions = actions || []; |
|||
groups = groups || []; |
|||
|
|||
|
|||
// if usage is specified, use that
|
|||
if (usage) { |
|||
usage = sprintf(usage, { prog: this._prog }); |
|||
|
|||
// if no optionals or positionals are available, usage is just prog
|
|||
} else if (!usage && actions.length === 0) { |
|||
usage = this._prog; |
|||
|
|||
// if optionals and positionals are available, calculate usage
|
|||
} else if (!usage) { |
|||
var prog = this._prog; |
|||
var optionals = []; |
|||
var positionals = []; |
|||
var actionUsage; |
|||
var textWidth; |
|||
|
|||
// split optionals from positionals
|
|||
actions.forEach(function (action) { |
|||
if (action.isOptional()) { |
|||
optionals.push(action); |
|||
} else { |
|||
positionals.push(action); |
|||
} |
|||
}); |
|||
|
|||
// build full usage string
|
|||
actionUsage = this._formatActionsUsage([].concat(optionals, positionals), groups); |
|||
usage = [ prog, actionUsage ].join(' '); |
|||
|
|||
// wrap the usage parts if it's too long
|
|||
textWidth = this._width - this._currentIndent; |
|||
if ((prefix.length + usage.length) > textWidth) { |
|||
|
|||
// break usage into wrappable parts
|
|||
var regexpPart = new RegExp('\\(.*?\\)+|\\[.*?\\]+|\\S+', 'g'); |
|||
var optionalUsage = this._formatActionsUsage(optionals, groups); |
|||
var positionalUsage = this._formatActionsUsage(positionals, groups); |
|||
|
|||
|
|||
var optionalParts = optionalUsage.match(regexpPart); |
|||
var positionalParts = positionalUsage.match(regexpPart) || []; |
|||
|
|||
if (optionalParts.join(' ') !== optionalUsage) { |
|||
throw new Error('assert "optionalParts.join(\' \') === optionalUsage"'); |
|||
} |
|||
if (positionalParts.join(' ') !== positionalUsage) { |
|||
throw new Error('assert "positionalParts.join(\' \') === positionalUsage"'); |
|||
} |
|||
|
|||
// helper for wrapping lines
|
|||
/*eslint-disable func-style*/ // node 0.10 compat
|
|||
var _getLines = function (parts, indent, prefix) { |
|||
var lines = []; |
|||
var line = []; |
|||
|
|||
var lineLength = prefix ? prefix.length - 1 : indent.length - 1; |
|||
|
|||
parts.forEach(function (part) { |
|||
if (lineLength + 1 + part.length > textWidth) { |
|||
lines.push(indent + line.join(' ')); |
|||
line = []; |
|||
lineLength = indent.length - 1; |
|||
} |
|||
line.push(part); |
|||
lineLength += part.length + 1; |
|||
}); |
|||
|
|||
if (line) { |
|||
lines.push(indent + line.join(' ')); |
|||
} |
|||
if (prefix) { |
|||
lines[0] = lines[0].substr(indent.length); |
|||
} |
|||
return lines; |
|||
}; |
|||
|
|||
var lines, indent, parts; |
|||
// if prog is short, follow it with optionals or positionals
|
|||
if (prefix.length + prog.length <= 0.75 * textWidth) { |
|||
indent = $$.repeat(' ', (prefix.length + prog.length + 1)); |
|||
if (optionalParts) { |
|||
lines = [].concat( |
|||
_getLines([ prog ].concat(optionalParts), indent, prefix), |
|||
_getLines(positionalParts, indent) |
|||
); |
|||
} else if (positionalParts) { |
|||
lines = _getLines([ prog ].concat(positionalParts), indent, prefix); |
|||
} else { |
|||
lines = [ prog ]; |
|||
} |
|||
|
|||
// if prog is long, put it on its own line
|
|||
} else { |
|||
indent = $$.repeat(' ', prefix.length); |
|||
parts = optionalParts.concat(positionalParts); |
|||
lines = _getLines(parts, indent); |
|||
if (lines.length > 1) { |
|||
lines = [].concat( |
|||
_getLines(optionalParts, indent), |
|||
_getLines(positionalParts, indent) |
|||
); |
|||
} |
|||
lines = [ prog ].concat(lines); |
|||
} |
|||
// join lines into usage
|
|||
usage = lines.join(c.EOL); |
|||
} |
|||
} |
|||
|
|||
// prefix with 'usage:'
|
|||
return prefix + usage + c.EOL + c.EOL; |
|||
}; |
|||
|
|||
HelpFormatter.prototype._formatActionsUsage = function (actions, groups) { |
|||
// find group indices and identify actions in groups
|
|||
var groupActions = []; |
|||
var inserts = []; |
|||
var self = this; |
|||
|
|||
groups.forEach(function (group) { |
|||
var end; |
|||
var i; |
|||
|
|||
var start = actions.indexOf(group._groupActions[0]); |
|||
if (start >= 0) { |
|||
end = start + group._groupActions.length; |
|||
|
|||
//if (actions.slice(start, end) === group._groupActions) {
|
|||
if ($$.arrayEqual(actions.slice(start, end), group._groupActions)) { |
|||
group._groupActions.forEach(function (action) { |
|||
groupActions.push(action); |
|||
}); |
|||
|
|||
if (!group.required) { |
|||
if (inserts[start]) { |
|||
inserts[start] += ' ['; |
|||
} else { |
|||
inserts[start] = '['; |
|||
} |
|||
inserts[end] = ']'; |
|||
} else { |
|||
if (inserts[start]) { |
|||
inserts[start] += ' ('; |
|||
} else { |
|||
inserts[start] = '('; |
|||
} |
|||
inserts[end] = ')'; |
|||
} |
|||
for (i = start + 1; i < end; i += 1) { |
|||
inserts[i] = '|'; |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
|
|||
// collect all actions format strings
|
|||
var parts = []; |
|||
|
|||
actions.forEach(function (action, actionIndex) { |
|||
var part; |
|||
var optionString; |
|||
var argsDefault; |
|||
var argsString; |
|||
|
|||
// suppressed arguments are marked with None
|
|||
// remove | separators for suppressed arguments
|
|||
if (action.help === c.SUPPRESS) { |
|||
parts.push(null); |
|||
if (inserts[actionIndex] === '|') { |
|||
inserts.splice(actionIndex, actionIndex); |
|||
} else if (inserts[actionIndex + 1] === '|') { |
|||
inserts.splice(actionIndex + 1, actionIndex + 1); |
|||
} |
|||
|
|||
// produce all arg strings
|
|||
} else if (!action.isOptional()) { |
|||
part = self._formatArgs(action, action.dest); |
|||
|
|||
// if it's in a group, strip the outer []
|
|||
if (groupActions.indexOf(action) >= 0) { |
|||
if (part[0] === '[' && part[part.length - 1] === ']') { |
|||
part = part.slice(1, -1); |
|||
} |
|||
} |
|||
// add the action string to the list
|
|||
parts.push(part); |
|||
|
|||
// produce the first way to invoke the option in brackets
|
|||
} else { |
|||
optionString = action.optionStrings[0]; |
|||
|
|||
// if the Optional doesn't take a value, format is: -s or --long
|
|||
if (action.nargs === 0) { |
|||
part = '' + optionString; |
|||
|
|||
// if the Optional takes a value, format is: -s ARGS or --long ARGS
|
|||
} else { |
|||
argsDefault = action.dest.toUpperCase(); |
|||
argsString = self._formatArgs(action, argsDefault); |
|||
part = optionString + ' ' + argsString; |
|||
} |
|||
// make it look optional if it's not required or in a group
|
|||
if (!action.required && groupActions.indexOf(action) < 0) { |
|||
part = '[' + part + ']'; |
|||
} |
|||
// add the action string to the list
|
|||
parts.push(part); |
|||
} |
|||
}); |
|||
|
|||
// insert things at the necessary indices
|
|||
for (var i = inserts.length - 1; i >= 0; --i) { |
|||
if (inserts[i] !== null) { |
|||
parts.splice(i, 0, inserts[i]); |
|||
} |
|||
} |
|||
|
|||
// join all the action items with spaces
|
|||
var text = parts.filter(function (part) { |
|||
return !!part; |
|||
}).join(' '); |
|||
|
|||
// clean up separators for mutually exclusive groups
|
|||
text = text.replace(/([\[(]) /g, '$1'); // remove spaces
|
|||
text = text.replace(/ ([\])])/g, '$1'); |
|||
text = text.replace(/\[ *\]/g, ''); // remove empty groups
|
|||
text = text.replace(/\( *\)/g, ''); |
|||
text = text.replace(/\(([^|]*)\)/g, '$1'); // remove () from single action groups
|
|||
|
|||
text = text.trim(); |
|||
|
|||
// return the text
|
|||
return text; |
|||
}; |
|||
|
|||
HelpFormatter.prototype._formatText = function (text) { |
|||
text = sprintf(text, { prog: this._prog }); |
|||
var textWidth = this._width - this._currentIndent; |
|||
var indentIncriment = $$.repeat(' ', this._currentIndent); |
|||
return this._fillText(text, textWidth, indentIncriment) + c.EOL + c.EOL; |
|||
}; |
|||
|
|||
HelpFormatter.prototype._formatAction = function (action) { |
|||
var self = this; |
|||
|
|||
var helpText; |
|||
var helpLines; |
|||
var parts; |
|||
var indentFirst; |
|||
|
|||
// determine the required width and the entry label
|
|||
var helpPosition = Math.min(this._actionMaxLength + 2, this._maxHelpPosition); |
|||
var helpWidth = this._width - helpPosition; |
|||
var actionWidth = helpPosition - this._currentIndent - 2; |
|||
var actionHeader = this._formatActionInvocation(action); |
|||
|
|||
// no help; start on same line and add a final newline
|
|||
if (!action.help) { |
|||
actionHeader = $$.repeat(' ', this._currentIndent) + actionHeader + c.EOL; |
|||
|
|||
// short action name; start on the same line and pad two spaces
|
|||
} else if (actionHeader.length <= actionWidth) { |
|||
actionHeader = $$.repeat(' ', this._currentIndent) + |
|||
actionHeader + |
|||
' ' + |
|||
$$.repeat(' ', actionWidth - actionHeader.length); |
|||
indentFirst = 0; |
|||
|
|||
// long action name; start on the next line
|
|||
} else { |
|||
actionHeader = $$.repeat(' ', this._currentIndent) + actionHeader + c.EOL; |
|||
indentFirst = helpPosition; |
|||
} |
|||
|
|||
// collect the pieces of the action help
|
|||
parts = [ actionHeader ]; |
|||
|
|||
// if there was help for the action, add lines of help text
|
|||
if (action.help) { |
|||
helpText = this._expandHelp(action); |
|||
helpLines = this._splitLines(helpText, helpWidth); |
|||
parts.push($$.repeat(' ', indentFirst) + helpLines[0] + c.EOL); |
|||
helpLines.slice(1).forEach(function (line) { |
|||
parts.push($$.repeat(' ', helpPosition) + line + c.EOL); |
|||
}); |
|||
|
|||
// or add a newline if the description doesn't end with one
|
|||
} else if (actionHeader.charAt(actionHeader.length - 1) !== c.EOL) { |
|||
parts.push(c.EOL); |
|||
} |
|||
// if there are any sub-actions, add their help as well
|
|||
if (action._getSubactions) { |
|||
this._indent(); |
|||
action._getSubactions().forEach(function (subaction) { |
|||
parts.push(self._formatAction(subaction)); |
|||
}); |
|||
this._dedent(); |
|||
} |
|||
// return a single string
|
|||
return this._joinParts(parts); |
|||
}; |
|||
|
|||
HelpFormatter.prototype._formatActionInvocation = function (action) { |
|||
if (!action.isOptional()) { |
|||
var format_func = this._metavarFormatter(action, action.dest); |
|||
var metavars = format_func(1); |
|||
return metavars[0]; |
|||
} |
|||
|
|||
var parts = []; |
|||
var argsDefault; |
|||
var argsString; |
|||
|
|||
// if the Optional doesn't take a value, format is: -s, --long
|
|||
if (action.nargs === 0) { |
|||
parts = parts.concat(action.optionStrings); |
|||
|
|||
// if the Optional takes a value, format is: -s ARGS, --long ARGS
|
|||
} else { |
|||
argsDefault = action.dest.toUpperCase(); |
|||
argsString = this._formatArgs(action, argsDefault); |
|||
action.optionStrings.forEach(function (optionString) { |
|||
parts.push(optionString + ' ' + argsString); |
|||
}); |
|||
} |
|||
return parts.join(', '); |
|||
}; |
|||
|
|||
HelpFormatter.prototype._metavarFormatter = function (action, metavarDefault) { |
|||
var result; |
|||
|
|||
if (action.metavar || action.metavar === '') { |
|||
result = action.metavar; |
|||
} else if (action.choices) { |
|||
var choices = action.choices; |
|||
|
|||
if (typeof choices === 'string') { |
|||
choices = choices.split('').join(', '); |
|||
} else if (Array.isArray(choices)) { |
|||
choices = choices.join(','); |
|||
} else { |
|||
choices = Object.keys(choices).join(','); |
|||
} |
|||
result = '{' + choices + '}'; |
|||
} else { |
|||
result = metavarDefault; |
|||
} |
|||
|
|||
return function (size) { |
|||
if (Array.isArray(result)) { |
|||
return result; |
|||
} |
|||
|
|||
var metavars = []; |
|||
for (var i = 0; i < size; i += 1) { |
|||
metavars.push(result); |
|||
} |
|||
return metavars; |
|||
}; |
|||
}; |
|||
|
|||
HelpFormatter.prototype._formatArgs = function (action, metavarDefault) { |
|||
var result; |
|||
var metavars; |
|||
|
|||
var buildMetavar = this._metavarFormatter(action, metavarDefault); |
|||
|
|||
switch (action.nargs) { |
|||
/*eslint-disable no-undefined*/ |
|||
case undefined: |
|||
case null: |
|||
metavars = buildMetavar(1); |
|||
result = '' + metavars[0]; |
|||
break; |
|||
case c.OPTIONAL: |
|||
metavars = buildMetavar(1); |
|||
result = '[' + metavars[0] + ']'; |
|||
break; |
|||
case c.ZERO_OR_MORE: |
|||
metavars = buildMetavar(2); |
|||
result = '[' + metavars[0] + ' [' + metavars[1] + ' ...]]'; |
|||
break; |
|||
case c.ONE_OR_MORE: |
|||
metavars = buildMetavar(2); |
|||
result = '' + metavars[0] + ' [' + metavars[1] + ' ...]'; |
|||
break; |
|||
case c.REMAINDER: |
|||
result = '...'; |
|||
break; |
|||
case c.PARSER: |
|||
metavars = buildMetavar(1); |
|||
result = metavars[0] + ' ...'; |
|||
break; |
|||
default: |
|||
metavars = buildMetavar(action.nargs); |
|||
result = metavars.join(' '); |
|||
} |
|||
return result; |
|||
}; |
|||
|
|||
HelpFormatter.prototype._expandHelp = function (action) { |
|||
var params = { prog: this._prog }; |
|||
|
|||
Object.keys(action).forEach(function (actionProperty) { |
|||
var actionValue = action[actionProperty]; |
|||
|
|||
if (actionValue !== c.SUPPRESS) { |
|||
params[actionProperty] = actionValue; |
|||
} |
|||
}); |
|||
|
|||
if (params.choices) { |
|||
if (typeof params.choices === 'string') { |
|||
params.choices = params.choices.split('').join(', '); |
|||
} else if (Array.isArray(params.choices)) { |
|||
params.choices = params.choices.join(', '); |
|||
} else { |
|||
params.choices = Object.keys(params.choices).join(', '); |
|||
} |
|||
} |
|||
|
|||
return sprintf(this._getHelpString(action), params); |
|||
}; |
|||
|
|||
HelpFormatter.prototype._splitLines = function (text, width) { |
|||
var lines = []; |
|||
var delimiters = [ ' ', '.', ',', '!', '?' ]; |
|||
var re = new RegExp('[' + delimiters.join('') + '][^' + delimiters.join('') + ']*$'); |
|||
|
|||
text = text.replace(/[\n\|\t]/g, ' '); |
|||
|
|||
text = text.trim(); |
|||
text = text.replace(this._whitespaceMatcher, ' '); |
|||
|
|||
// Wraps the single paragraph in text (a string) so every line
|
|||
// is at most width characters long.
|
|||
text.split(c.EOL).forEach(function (line) { |
|||
if (width >= line.length) { |
|||
lines.push(line); |
|||
return; |
|||
} |
|||
|
|||
var wrapStart = 0; |
|||
var wrapEnd = width; |
|||
var delimiterIndex = 0; |
|||
while (wrapEnd <= line.length) { |
|||
if (wrapEnd !== line.length && delimiters.indexOf(line[wrapEnd] < -1)) { |
|||
delimiterIndex = (re.exec(line.substring(wrapStart, wrapEnd)) || {}).index; |
|||
wrapEnd = wrapStart + delimiterIndex + 1; |
|||
} |
|||
lines.push(line.substring(wrapStart, wrapEnd)); |
|||
wrapStart = wrapEnd; |
|||
wrapEnd += width; |
|||
} |
|||
if (wrapStart < line.length) { |
|||
lines.push(line.substring(wrapStart, wrapEnd)); |
|||
} |
|||
}); |
|||
|
|||
return lines; |
|||
}; |
|||
|
|||
HelpFormatter.prototype._fillText = function (text, width, indent) { |
|||
var lines = this._splitLines(text, width); |
|||
lines = lines.map(function (line) { |
|||
return indent + line; |
|||
}); |
|||
return lines.join(c.EOL); |
|||
}; |
|||
|
|||
HelpFormatter.prototype._getHelpString = function (action) { |
|||
return action.help; |
|||
}; |
@ -0,0 +1,76 @@ |
|||
/** |
|||
* class Namespace |
|||
* |
|||
* Simple object for storing attributes. Implements equality by attribute names |
|||
* and values, and provides a simple string representation. |
|||
* |
|||
* See also [original guide][1] |
|||
* |
|||
* [1]:http://docs.python.org/dev/library/argparse.html#the-namespace-object
|
|||
**/ |
|||
'use strict'; |
|||
|
|||
var $$ = require('./utils'); |
|||
|
|||
/** |
|||
* new Namespace(options) |
|||
* - options(object): predefined propertis for result object |
|||
* |
|||
**/ |
|||
var Namespace = module.exports = function Namespace(options) { |
|||
$$.extend(this, options); |
|||
}; |
|||
|
|||
/** |
|||
* Namespace#isset(key) -> Boolean |
|||
* - key (string|number): property name |
|||
* |
|||
* Tells whenever `namespace` contains given `key` or not. |
|||
**/ |
|||
Namespace.prototype.isset = function (key) { |
|||
return $$.has(this, key); |
|||
}; |
|||
|
|||
/** |
|||
* Namespace#set(key, value) -> self |
|||
* -key (string|number|object): propery name |
|||
* -value (mixed): new property value |
|||
* |
|||
* Set the property named key with value. |
|||
* If key object then set all key properties to namespace object |
|||
**/ |
|||
Namespace.prototype.set = function (key, value) { |
|||
if (typeof (key) === 'object') { |
|||
$$.extend(this, key); |
|||
} else { |
|||
this[key] = value; |
|||
} |
|||
return this; |
|||
}; |
|||
|
|||
/** |
|||
* Namespace#get(key, defaultValue) -> mixed |
|||
* - key (string|number): property name |
|||
* - defaultValue (mixed): default value |
|||
* |
|||
* Return the property key or defaulValue if not set |
|||
**/ |
|||
Namespace.prototype.get = function (key, defaultValue) { |
|||
return !this[key] ? defaultValue : this[key]; |
|||
}; |
|||
|
|||
/** |
|||
* Namespace#unset(key, defaultValue) -> mixed |
|||
* - key (string|number): property name |
|||
* - defaultValue (mixed): default value |
|||
* |
|||
* Return data[key](and delete it) or defaultValue |
|||
**/ |
|||
Namespace.prototype.unset = function (key, defaultValue) { |
|||
var value = this[key]; |
|||
if (value !== null) { |
|||
delete this[key]; |
|||
return value; |
|||
} |
|||
return defaultValue; |
|||
}; |
@ -0,0 +1,57 @@ |
|||
'use strict'; |
|||
|
|||
exports.repeat = function (str, num) { |
|||
var result = ''; |
|||
for (var i = 0; i < num; i++) { result += str; } |
|||
return result; |
|||
}; |
|||
|
|||
exports.arrayEqual = function (a, b) { |
|||
if (a.length !== b.length) { return false; } |
|||
for (var i = 0; i < a.length; i++) { |
|||
if (a[i] !== b[i]) { return false; } |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
exports.trimChars = function (str, chars) { |
|||
var start = 0; |
|||
var end = str.length - 1; |
|||
while (chars.indexOf(str.charAt(start)) >= 0) { start++; } |
|||
while (chars.indexOf(str.charAt(end)) >= 0) { end--; } |
|||
return str.slice(start, end + 1); |
|||
}; |
|||
|
|||
exports.capitalize = function (str) { |
|||
return str.charAt(0).toUpperCase() + str.slice(1); |
|||
}; |
|||
|
|||
exports.arrayUnion = function () { |
|||
var result = []; |
|||
for (var i = 0, values = {}; i < arguments.length; i++) { |
|||
var arr = arguments[i]; |
|||
for (var j = 0; j < arr.length; j++) { |
|||
if (!values[arr[j]]) { |
|||
values[arr[j]] = true; |
|||
result.push(arr[j]); |
|||
} |
|||
} |
|||
} |
|||
return result; |
|||
}; |
|||
|
|||
function has(obj, key) { |
|||
return Object.prototype.hasOwnProperty.call(obj, key); |
|||
} |
|||
|
|||
exports.has = has; |
|||
|
|||
exports.extend = function (dest, src) { |
|||
for (var i in src) { |
|||
if (has(src, i)) { dest[i] = src[i]; } |
|||
} |
|||
}; |
|||
|
|||
exports.trimEnd = function (str) { |
|||
return str.replace(/\s+$/g, ''); |
|||
}; |
@ -0,0 +1,70 @@ |
|||
{ |
|||
"_from": "argparse@1.0.10", |
|||
"_id": "argparse@1.0.10", |
|||
"_inBundle": false, |
|||
"_integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", |
|||
"_location": "/argparse", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "version", |
|||
"registry": true, |
|||
"raw": "argparse@1.0.10", |
|||
"name": "argparse", |
|||
"escapedName": "argparse", |
|||
"rawSpec": "1.0.10", |
|||
"saveSpec": null, |
|||
"fetchSpec": "1.0.10" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/markdown-it" |
|||
], |
|||
"_resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", |
|||
"_shasum": "bcd6791ea5ae09725e17e5ad988134cd40b3d911", |
|||
"_spec": "argparse@1.0.10", |
|||
"_where": "/home/rohan/git/chatto-spring/chatto/src/main/javascript/node_modules/markdown-it", |
|||
"bugs": { |
|||
"url": "https://github.com/nodeca/argparse/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"contributors": [ |
|||
{ |
|||
"name": "Eugene Shkuropat" |
|||
}, |
|||
{ |
|||
"name": "Paul Jacobson" |
|||
} |
|||
], |
|||
"dependencies": { |
|||
"sprintf-js": "~1.0.2" |
|||
}, |
|||
"deprecated": false, |
|||
"description": "Very powerful CLI arguments parser. Native port of argparse - python's options parsing library", |
|||
"devDependencies": { |
|||
"eslint": "^2.13.1", |
|||
"istanbul": "^0.4.5", |
|||
"mocha": "^3.1.0", |
|||
"ndoc": "^5.0.1" |
|||
}, |
|||
"files": [ |
|||
"index.js", |
|||
"lib/" |
|||
], |
|||
"homepage": "https://github.com/nodeca/argparse#readme", |
|||
"keywords": [ |
|||
"cli", |
|||
"parser", |
|||
"argparse", |
|||
"option", |
|||
"args" |
|||
], |
|||
"license": "MIT", |
|||
"name": "argparse", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/nodeca/argparse.git" |
|||
}, |
|||
"scripts": { |
|||
"test": "make test" |
|||
}, |
|||
"version": "1.0.10" |
|||
} |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2014-2017, Jon Schlinkert |
|||
|
|||
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,130 @@ |
|||
# arr-diff [![NPM version](https://img.shields.io/npm/v/arr-diff.svg?style=flat)](https://www.npmjs.com/package/arr-diff) [![NPM monthly downloads](https://img.shields.io/npm/dm/arr-diff.svg?style=flat)](https://npmjs.org/package/arr-diff) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/arr-diff.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/arr-diff) |
|||
|
|||
> Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons. |
|||
|
|||
## Install |
|||
|
|||
Install with [npm](https://www.npmjs.com/): |
|||
|
|||
```sh |
|||
$ npm install --save arr-diff |
|||
``` |
|||
|
|||
Install with [yarn](https://yarnpkg.com): |
|||
|
|||
```sh |
|||
$ yarn add arr-diff |
|||
``` |
|||
|
|||
Install with [bower](https://bower.io/) |
|||
|
|||
```sh |
|||
$ bower install arr-diff --save |
|||
``` |
|||
|
|||
## Usage |
|||
|
|||
Returns the difference between the first array and additional arrays. |
|||
|
|||
```js |
|||
var diff = require('arr-diff'); |
|||
|
|||
var a = ['a', 'b', 'c', 'd']; |
|||
var b = ['b', 'c']; |
|||
|
|||
console.log(diff(a, b)) |
|||
//=> ['a', 'd'] |
|||
``` |
|||
|
|||
## Benchmarks |
|||
|
|||
This library versus [array-differ](https://github.com/sindresorhus/array-differ), on April 14, 2017: |
|||
|
|||
``` |
|||
Benchmarking: (4 of 4) |
|||
· long-dupes |
|||
· long |
|||
· med |
|||
· short |
|||
|
|||
# benchmark/fixtures/long-dupes.js (100804 bytes) |
|||
arr-diff-3.0.0 x 822 ops/sec ±0.67% (86 runs sampled) |
|||
arr-diff-4.0.0 x 2,141 ops/sec ±0.42% (89 runs sampled) |
|||
array-differ x 708 ops/sec ±0.70% (89 runs sampled) |
|||
|
|||
fastest is arr-diff-4.0.0 |
|||
|
|||
# benchmark/fixtures/long.js (94529 bytes) |
|||
arr-diff-3.0.0 x 882 ops/sec ±0.60% (87 runs sampled) |
|||
arr-diff-4.0.0 x 2,329 ops/sec ±0.97% (83 runs sampled) |
|||
array-differ x 769 ops/sec ±0.61% (90 runs sampled) |
|||
|
|||
fastest is arr-diff-4.0.0 |
|||
|
|||
# benchmark/fixtures/med.js (708 bytes) |
|||
arr-diff-3.0.0 x 856,150 ops/sec ±0.42% (89 runs sampled) |
|||
arr-diff-4.0.0 x 4,665,249 ops/sec ±1.06% (89 runs sampled) |
|||
array-differ x 653,888 ops/sec ±1.02% (86 runs sampled) |
|||
|
|||
fastest is arr-diff-4.0.0 |
|||
|
|||
# benchmark/fixtures/short.js (60 bytes) |
|||
arr-diff-3.0.0 x 3,078,467 ops/sec ±0.77% (93 runs sampled) |
|||
arr-diff-4.0.0 x 9,213,296 ops/sec ±0.65% (89 runs sampled) |
|||
array-differ x 1,337,051 ops/sec ±0.91% (92 runs sampled) |
|||
|
|||
fastest is arr-diff-4.0.0 |
|||
``` |
|||
|
|||
## About |
|||
|
|||
### Related projects |
|||
|
|||
* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten "Recursively flatten an array or arrays. This is the fastest implementation of array flatten.") |
|||
* [array-filter](https://www.npmjs.com/package/array-filter): Array#filter for older browsers. | [homepage](https://github.com/juliangruber/array-filter "Array#filter for older browsers.") |
|||
* [array-intersection](https://www.npmjs.com/package/array-intersection): Return an array with the unique values present in _all_ given arrays using strict equality… [more](https://github.com/jonschlinkert/array-intersection) | [homepage](https://github.com/jonschlinkert/array-intersection "Return an array with the unique values present in _all_ given arrays using strict equality for comparisons.") |
|||
|
|||
### Contributing |
|||
|
|||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). |
|||
|
|||
### Contributors |
|||
|
|||
| **Commits** | **Contributor** | |
|||
| --- | --- | |
|||
| 33 | [jonschlinkert](https://github.com/jonschlinkert) | |
|||
| 2 | [paulmillr](https://github.com/paulmillr) | |
|||
|
|||
### Building docs |
|||
|
|||
_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ |
|||
|
|||
To generate the readme, run the following command: |
|||
|
|||
```sh |
|||
$ npm install -g verbose/verb#dev verb-generate-readme && verb |
|||
``` |
|||
|
|||
### Running tests |
|||
|
|||
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: |
|||
|
|||
```sh |
|||
$ npm install && npm test |
|||
``` |
|||
|
|||
### Author |
|||
|
|||
**Jon Schlinkert** |
|||
|
|||
* [github/jonschlinkert](https://github.com/jonschlinkert) |
|||
* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) |
|||
|
|||
### License |
|||
|
|||
Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). |
|||
Released under the [MIT License](LICENSE). |
|||
|
|||
*** |
|||
|
|||
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.5.0, on April 14, 2017._ |
@ -0,0 +1,47 @@ |
|||
/*! |
|||
* arr-diff <https://github.com/jonschlinkert/arr-diff>
|
|||
* |
|||
* Copyright (c) 2014-2017, Jon Schlinkert. |
|||
* Released under the MIT License. |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
module.exports = function diff(arr/*, arrays*/) { |
|||
var len = arguments.length; |
|||
var idx = 0; |
|||
while (++idx < len) { |
|||
arr = diffArray(arr, arguments[idx]); |
|||
} |
|||
return arr; |
|||
}; |
|||
|
|||
function diffArray(one, two) { |
|||
if (!Array.isArray(two)) { |
|||
return one.slice(); |
|||
} |
|||
|
|||
var tlen = two.length |
|||
var olen = one.length; |
|||
var idx = -1; |
|||
var arr = []; |
|||
|
|||
while (++idx < olen) { |
|||
var ele = one[idx]; |
|||
|
|||
var hasEle = false; |
|||
for (var i = 0; i < tlen; i++) { |
|||
var val = two[i]; |
|||
|
|||
if (ele === val) { |
|||
hasEle = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (hasEle === false) { |
|||
arr.push(ele); |
|||
} |
|||
} |
|||
return arr; |
|||
} |
@ -0,0 +1,109 @@ |
|||
{ |
|||
"_from": "arr-diff@^4.0.0", |
|||
"_id": "arr-diff@4.0.0", |
|||
"_inBundle": false, |
|||
"_integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", |
|||
"_location": "/arr-diff", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "range", |
|||
"registry": true, |
|||
"raw": "arr-diff@^4.0.0", |
|||
"name": "arr-diff", |
|||
"escapedName": "arr-diff", |
|||
"rawSpec": "^4.0.0", |
|||
"saveSpec": null, |
|||
"fetchSpec": "^4.0.0" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/micromatch", |
|||
"/nanomatch" |
|||
], |
|||
"_resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", |
|||
"_shasum": "d6461074febfec71e7e15235761a329a5dc7c520", |
|||
"_spec": "arr-diff@^4.0.0", |
|||
"_where": "/home/rohan/git/chatto-spring/chatto/src/main/javascript/node_modules/micromatch", |
|||
"author": { |
|||
"name": "Jon Schlinkert", |
|||
"url": "https://github.com/jonschlinkert" |
|||
}, |
|||
"bugs": { |
|||
"url": "https://github.com/jonschlinkert/arr-diff/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"contributors": [ |
|||
{ |
|||
"name": "Jon Schlinkert", |
|||
"email": "jon.schlinkert@sellside.com", |
|||
"url": "http://twitter.com/jonschlinkert" |
|||
}, |
|||
{ |
|||
"name": "Paul Miller", |
|||
"email": "paul+gh@paulmillr.com", |
|||
"url": "paulmillr.com" |
|||
} |
|||
], |
|||
"dependencies": {}, |
|||
"deprecated": false, |
|||
"description": "Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons.", |
|||
"devDependencies": { |
|||
"ansi-bold": "^0.1.1", |
|||
"arr-flatten": "^1.0.1", |
|||
"array-differ": "^1.0.0", |
|||
"benchmarked": "^0.2.4", |
|||
"gulp-format-md": "^0.1.9", |
|||
"minimist": "^1.2.0", |
|||
"mocha": "^2.4.5" |
|||
}, |
|||
"engines": { |
|||
"node": ">=0.10.0" |
|||
}, |
|||
"files": [ |
|||
"index.js" |
|||
], |
|||
"homepage": "https://github.com/jonschlinkert/arr-diff", |
|||
"keywords": [ |
|||
"arr", |
|||
"array", |
|||
"array differ", |
|||
"array-differ", |
|||
"diff", |
|||
"differ", |
|||
"difference" |
|||
], |
|||
"license": "MIT", |
|||
"main": "index.js", |
|||
"name": "arr-diff", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/jonschlinkert/arr-diff.git" |
|||
}, |
|||
"scripts": { |
|||
"test": "mocha" |
|||
}, |
|||
"verb": { |
|||
"toc": false, |
|||
"layout": "default", |
|||
"tasks": [ |
|||
"readme" |
|||
], |
|||
"plugins": [ |
|||
"gulp-format-md" |
|||
], |
|||
"related": { |
|||
"list": [ |
|||
"arr-flatten", |
|||
"array-filter", |
|||
"array-intersection" |
|||
] |
|||
}, |
|||
"reflinks": [ |
|||
"array-differ", |
|||
"verb" |
|||
], |
|||
"lint": { |
|||
"reflinks": true |
|||
} |
|||
}, |
|||
"version": "4.0.0" |
|||
} |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2014-2017, Jon Schlinkert. |
|||
|
|||
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,86 @@ |
|||
# arr-flatten [![NPM version](https://img.shields.io/npm/v/arr-flatten.svg?style=flat)](https://www.npmjs.com/package/arr-flatten) [![NPM monthly downloads](https://img.shields.io/npm/dm/arr-flatten.svg?style=flat)](https://npmjs.org/package/arr-flatten) [![NPM total downloads](https://img.shields.io/npm/dt/arr-flatten.svg?style=flat)](https://npmjs.org/package/arr-flatten) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/arr-flatten.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/arr-flatten) [![Windows Build Status](https://img.shields.io/appveyor/ci/jonschlinkert/arr-flatten.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/jonschlinkert/arr-flatten) |
|||
|
|||
> Recursively flatten an array or arrays. |
|||
|
|||
## Install |
|||
|
|||
Install with [npm](https://www.npmjs.com/): |
|||
|
|||
```sh |
|||
$ npm install --save arr-flatten |
|||
``` |
|||
|
|||
## Install |
|||
|
|||
Install with [bower](https://bower.io/) |
|||
|
|||
```sh |
|||
$ bower install arr-flatten --save |
|||
``` |
|||
|
|||
## Usage |
|||
|
|||
```js |
|||
var flatten = require('arr-flatten'); |
|||
|
|||
flatten(['a', ['b', ['c']], 'd', ['e']]); |
|||
//=> ['a', 'b', 'c', 'd', 'e'] |
|||
``` |
|||
|
|||
## Why another flatten utility? |
|||
|
|||
I wanted the fastest implementation I could find, with implementation choices that should work for 95% of use cases, but no cruft to cover the other 5%. |
|||
|
|||
## About |
|||
|
|||
### Related projects |
|||
|
|||
* [arr-filter](https://www.npmjs.com/package/arr-filter): Faster alternative to javascript's native filter method. | [homepage](https://github.com/jonschlinkert/arr-filter "Faster alternative to javascript's native filter method.") |
|||
* [arr-union](https://www.npmjs.com/package/arr-union): Combines a list of arrays, returning a single array with unique values, using strict equality… [more](https://github.com/jonschlinkert/arr-union) | [homepage](https://github.com/jonschlinkert/arr-union "Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons.") |
|||
* [array-each](https://www.npmjs.com/package/array-each): Loop over each item in an array and call the given function on every element. | [homepage](https://github.com/jonschlinkert/array-each "Loop over each item in an array and call the given function on every element.") |
|||
* [array-unique](https://www.npmjs.com/package/array-unique): Remove duplicate values from an array. Fastest ES5 implementation. | [homepage](https://github.com/jonschlinkert/array-unique "Remove duplicate values from an array. Fastest ES5 implementation.") |
|||
|
|||
### Contributing |
|||
|
|||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). |
|||
|
|||
### Contributors |
|||
|
|||
| **Commits** | **Contributor** | |
|||
| --- | --- | |
|||
| 20 | [jonschlinkert](https://github.com/jonschlinkert) | |
|||
| 1 | [lukeed](https://github.com/lukeed) | |
|||
|
|||
### Building docs |
|||
|
|||
_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ |
|||
|
|||
To generate the readme, run the following command: |
|||
|
|||
```sh |
|||
$ npm install -g verbose/verb#dev verb-generate-readme && verb |
|||
``` |
|||
|
|||
### Running tests |
|||
|
|||
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: |
|||
|
|||
```sh |
|||
$ npm install && npm test |
|||
``` |
|||
|
|||
### Author |
|||
|
|||
**Jon Schlinkert** |
|||
|
|||
* [github/jonschlinkert](https://github.com/jonschlinkert) |
|||
* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) |
|||
|
|||
### License |
|||
|
|||
Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). |
|||
Released under the [MIT License](LICENSE). |
|||
|
|||
*** |
|||
|
|||
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 05, 2017._ |
@ -0,0 +1,22 @@ |
|||
/*! |
|||
* arr-flatten <https://github.com/jonschlinkert/arr-flatten>
|
|||
* |
|||
* Copyright (c) 2014-2017, Jon Schlinkert. |
|||
* Released under the MIT License. |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
module.exports = function (arr) { |
|||
return flat(arr, []); |
|||
}; |
|||
|
|||
function flat(arr, res) { |
|||
var i = 0, cur; |
|||
var len = arr.length; |
|||
for (; i < len; i++) { |
|||
cur = arr[i]; |
|||
Array.isArray(cur) ? flat(cur, res) : res.push(cur); |
|||
} |
|||
return res; |
|||
} |
@ -0,0 +1,113 @@ |
|||
{ |
|||
"_from": "arr-flatten@^1.1.0", |
|||
"_id": "arr-flatten@1.1.0", |
|||
"_inBundle": false, |
|||
"_integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", |
|||
"_location": "/arr-flatten", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "range", |
|||
"registry": true, |
|||
"raw": "arr-flatten@^1.1.0", |
|||
"name": "arr-flatten", |
|||
"escapedName": "arr-flatten", |
|||
"rawSpec": "^1.1.0", |
|||
"saveSpec": null, |
|||
"fetchSpec": "^1.1.0" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/braces" |
|||
], |
|||
"_resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", |
|||
"_shasum": "36048bbff4e7b47e136644316c99669ea5ae91f1", |
|||
"_spec": "arr-flatten@^1.1.0", |
|||
"_where": "/home/rohan/git/chatto-spring/chatto/src/main/javascript/node_modules/braces", |
|||
"author": { |
|||
"name": "Jon Schlinkert", |
|||
"url": "https://github.com/jonschlinkert" |
|||
}, |
|||
"bugs": { |
|||
"url": "https://github.com/jonschlinkert/arr-flatten/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"contributors": [ |
|||
{ |
|||
"name": "Jon Schlinkert", |
|||
"url": "http://twitter.com/jonschlinkert" |
|||
}, |
|||
{ |
|||
"name": "Luke Edwards", |
|||
"url": "https://lukeed.com" |
|||
} |
|||
], |
|||
"deprecated": false, |
|||
"description": "Recursively flatten an array or arrays.", |
|||
"devDependencies": { |
|||
"ansi-bold": "^0.1.1", |
|||
"array-flatten": "^2.1.1", |
|||
"array-slice": "^1.0.0", |
|||
"benchmarked": "^1.0.0", |
|||
"compute-flatten": "^1.0.0", |
|||
"flatit": "^1.1.1", |
|||
"flatten": "^1.0.2", |
|||
"flatten-array": "^1.0.0", |
|||
"glob": "^7.1.1", |
|||
"gulp-format-md": "^0.1.12", |
|||
"just-flatten-it": "^1.1.23", |
|||
"lodash.flattendeep": "^4.4.0", |
|||
"m_flattened": "^1.0.1", |
|||
"mocha": "^3.2.0", |
|||
"utils-flatten": "^1.0.0", |
|||
"write": "^0.3.3" |
|||
}, |
|||
"engines": { |
|||
"node": ">=0.10.0" |
|||
}, |
|||
"files": [ |
|||
"index.js" |
|||
], |
|||
"homepage": "https://github.com/jonschlinkert/arr-flatten", |
|||
"keywords": [ |
|||
"arr", |
|||
"array", |
|||
"elements", |
|||
"flat", |
|||
"flatten", |
|||
"nested", |
|||
"recurse", |
|||
"recursive", |
|||
"recursively" |
|||
], |
|||
"license": "MIT", |
|||
"main": "index.js", |
|||
"name": "arr-flatten", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/jonschlinkert/arr-flatten.git" |
|||
}, |
|||
"scripts": { |
|||
"test": "mocha" |
|||
}, |
|||
"verb": { |
|||
"toc": false, |
|||
"layout": "default", |
|||
"tasks": [ |
|||
"readme" |
|||
], |
|||
"plugins": [ |
|||
"gulp-format-md" |
|||
], |
|||
"related": { |
|||
"list": [ |
|||
"arr-filter", |
|||
"arr-union", |
|||
"array-each", |
|||
"array-unique" |
|||
] |
|||
}, |
|||
"lint": { |
|||
"reflinks": true |
|||
} |
|||
}, |
|||
"version": "1.1.0" |
|||
} |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2014-2016, Jon Schlinkert. |
|||
|
|||
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,99 @@ |
|||
# arr-union [![NPM version](https://img.shields.io/npm/v/arr-union.svg)](https://www.npmjs.com/package/arr-union) [![Build Status](https://img.shields.io/travis/jonschlinkert/arr-union.svg)](https://travis-ci.org/jonschlinkert/arr-union) |
|||
|
|||
> Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons. |
|||
|
|||
## Install |
|||
|
|||
Install with [npm](https://www.npmjs.com/): |
|||
|
|||
```sh |
|||
$ npm i arr-union --save |
|||
``` |
|||
|
|||
## Benchmarks |
|||
|
|||
This library is **10-20 times faster** and more performant than [array-union](https://github.com/sindresorhus/array-union). |
|||
|
|||
See the [benchmarks](./benchmark). |
|||
|
|||
```sh |
|||
#1: five-arrays |
|||
array-union x 511,121 ops/sec ±0.80% (96 runs sampled) |
|||
arr-union x 5,716,039 ops/sec ±0.86% (93 runs sampled) |
|||
|
|||
#2: ten-arrays |
|||
array-union x 245,196 ops/sec ±0.69% (94 runs sampled) |
|||
arr-union x 1,850,786 ops/sec ±0.84% (97 runs sampled) |
|||
|
|||
#3: two-arrays |
|||
array-union x 563,869 ops/sec ±0.97% (94 runs sampled) |
|||
arr-union x 9,602,852 ops/sec ±0.87% (92 runs sampled) |
|||
``` |
|||
|
|||
## Usage |
|||
|
|||
```js |
|||
var union = require('arr-union'); |
|||
|
|||
union(['a'], ['b', 'c'], ['d', 'e', 'f']); |
|||
//=> ['a', 'b', 'c', 'd', 'e', 'f'] |
|||
``` |
|||
|
|||
Returns only unique elements: |
|||
|
|||
```js |
|||
union(['a', 'a'], ['b', 'c']); |
|||
//=> ['a', 'b', 'c'] |
|||
``` |
|||
|
|||
## Related projects |
|||
|
|||
* [arr-diff](https://www.npmjs.com/package/arr-diff): Returns an array with only the unique values from the first array, by excluding all… [more](https://www.npmjs.com/package/arr-diff) | [homepage](https://github.com/jonschlinkert/arr-diff) |
|||
* [arr-filter](https://www.npmjs.com/package/arr-filter): Faster alternative to javascript's native filter method. | [homepage](https://github.com/jonschlinkert/arr-filter) |
|||
* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten) |
|||
* [arr-map](https://www.npmjs.com/package/arr-map): Faster, node.js focused alternative to JavaScript's native array map. | [homepage](https://github.com/jonschlinkert/arr-map) |
|||
* [arr-pluck](https://www.npmjs.com/package/arr-pluck): Retrieves the value of a specified property from all elements in the collection. | [homepage](https://github.com/jonschlinkert/arr-pluck) |
|||
* [arr-reduce](https://www.npmjs.com/package/arr-reduce): Fast array reduce that also loops over sparse elements. | [homepage](https://github.com/jonschlinkert/arr-reduce) |
|||
* [array-unique](https://www.npmjs.com/package/array-unique): Return an array free of duplicate values. Fastest ES5 implementation. | [homepage](https://github.com/jonschlinkert/array-unique) |
|||
|
|||
## Contributing |
|||
|
|||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/arr-union/issues/new). |
|||
|
|||
## Building docs |
|||
|
|||
Generate readme and API documentation with [verb](https://github.com/verbose/verb): |
|||
|
|||
```sh |
|||
$ npm i verb && npm run docs |
|||
``` |
|||
|
|||
Or, if [verb](https://github.com/verbose/verb) is installed globally: |
|||
|
|||
```sh |
|||
$ verb |
|||
``` |
|||
|
|||
## Running tests |
|||
|
|||
Install dev dependencies: |
|||
|
|||
```sh |
|||
$ npm i -d && npm test |
|||
``` |
|||
|
|||
## Author |
|||
|
|||
**Jon Schlinkert** |
|||
|
|||
* [github/jonschlinkert](https://github.com/jonschlinkert) |
|||
* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) |
|||
|
|||
## License |
|||
|
|||
Copyright © 2016 [Jon Schlinkert](https://github.com/jonschlinkert) |
|||
Released under the [MIT license](https://github.com/jonschlinkert/arr-union/blob/master/LICENSE). |
|||
|
|||
*** |
|||
|
|||
_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on February 23, 2016._ |
@ -0,0 +1,29 @@ |
|||
'use strict'; |
|||
|
|||
module.exports = function union(init) { |
|||
if (!Array.isArray(init)) { |
|||
throw new TypeError('arr-union expects the first argument to be an array.'); |
|||
} |
|||
|
|||
var len = arguments.length; |
|||
var i = 0; |
|||
|
|||
while (++i < len) { |
|||
var arg = arguments[i]; |
|||
if (!arg) continue; |
|||
|
|||
if (!Array.isArray(arg)) { |
|||
arg = [arg]; |
|||
} |
|||
|
|||
for (var j = 0; j < arg.length; j++) { |
|||
var ele = arg[j]; |
|||
|
|||
if (init.indexOf(ele) >= 0) { |
|||
continue; |
|||
} |
|||
init.push(ele); |
|||
} |
|||
} |
|||
return init; |
|||
}; |
@ -0,0 +1,108 @@ |
|||
{ |
|||
"_from": "arr-union@^3.1.0", |
|||
"_id": "arr-union@3.1.0", |
|||
"_inBundle": false, |
|||
"_integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", |
|||
"_location": "/arr-union", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "range", |
|||
"registry": true, |
|||
"raw": "arr-union@^3.1.0", |
|||
"name": "arr-union", |
|||
"escapedName": "arr-union", |
|||
"rawSpec": "^3.1.0", |
|||
"saveSpec": null, |
|||
"fetchSpec": "^3.1.0" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/class-utils", |
|||
"/union-value" |
|||
], |
|||
"_resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", |
|||
"_shasum": "e39b09aea9def866a8f206e288af63919bae39c4", |
|||
"_spec": "arr-union@^3.1.0", |
|||
"_where": "/home/rohan/git/chatto-spring/chatto/src/main/javascript/node_modules/union-value", |
|||
"author": { |
|||
"name": "Jon Schlinkert", |
|||
"url": "https://github.com/jonschlinkert" |
|||
}, |
|||
"bugs": { |
|||
"url": "https://github.com/jonschlinkert/arr-union/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"deprecated": false, |
|||
"description": "Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons.", |
|||
"devDependencies": { |
|||
"ansi-bold": "^0.1.1", |
|||
"array-union": "^1.0.1", |
|||
"array-unique": "^0.2.1", |
|||
"benchmarked": "^0.1.4", |
|||
"gulp-format-md": "^0.1.7", |
|||
"minimist": "^1.1.1", |
|||
"mocha": "*", |
|||
"should": "*" |
|||
}, |
|||
"engines": { |
|||
"node": ">=0.10.0" |
|||
}, |
|||
"files": [ |
|||
"index.js" |
|||
], |
|||
"homepage": "https://github.com/jonschlinkert/arr-union", |
|||
"keywords": [ |
|||
"add", |
|||
"append", |
|||
"array", |
|||
"arrays", |
|||
"combine", |
|||
"concat", |
|||
"extend", |
|||
"union", |
|||
"uniq", |
|||
"unique", |
|||
"util", |
|||
"utility", |
|||
"utils" |
|||
], |
|||
"license": "MIT", |
|||
"main": "index.js", |
|||
"name": "arr-union", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/jonschlinkert/arr-union.git" |
|||
}, |
|||
"scripts": { |
|||
"test": "mocha" |
|||
}, |
|||
"verb": { |
|||
"run": true, |
|||
"toc": false, |
|||
"layout": "default", |
|||
"tasks": [ |
|||
"readme" |
|||
], |
|||
"plugins": [ |
|||
"gulp-format-md" |
|||
], |
|||
"related": { |
|||
"list": [ |
|||
"arr-diff", |
|||
"arr-flatten", |
|||
"arr-filter", |
|||
"arr-map", |
|||
"arr-pluck", |
|||
"arr-reduce", |
|||
"array-unique" |
|||
] |
|||
}, |
|||
"reflinks": [ |
|||
"verb", |
|||
"array-union" |
|||
], |
|||
"lint": { |
|||
"reflinks": true |
|||
} |
|||
}, |
|||
"version": "3.1.0" |
|||
} |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2014-2016, Jon Schlinkert |
|||
|
|||
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,77 @@ |
|||
# array-unique [![NPM version](https://img.shields.io/npm/v/array-unique.svg?style=flat)](https://www.npmjs.com/package/array-unique) [![NPM downloads](https://img.shields.io/npm/dm/array-unique.svg?style=flat)](https://npmjs.org/package/array-unique) [![Build Status](https://img.shields.io/travis/jonschlinkert/array-unique.svg?style=flat)](https://travis-ci.org/jonschlinkert/array-unique) |
|||
|
|||
Remove duplicate values from an array. Fastest ES5 implementation. |
|||
|
|||
## Install |
|||
|
|||
Install with [npm](https://www.npmjs.com/): |
|||
|
|||
```sh |
|||
$ npm install --save array-unique |
|||
``` |
|||
|
|||
## Usage |
|||
|
|||
```js |
|||
var unique = require('array-unique'); |
|||
|
|||
var arr = ['a', 'b', 'c', 'c']; |
|||
console.log(unique(arr)) //=> ['a', 'b', 'c'] |
|||
console.log(arr) //=> ['a', 'b', 'c'] |
|||
|
|||
/* The above modifies the input array. To prevent that at a slight performance cost: */ |
|||
var unique = require("array-unique").immutable; |
|||
|
|||
var arr = ['a', 'b', 'c', 'c']; |
|||
console.log(unique(arr)) //=> ['a', 'b', 'c'] |
|||
console.log(arr) //=> ['a', 'b', 'c', 'c'] |
|||
``` |
|||
|
|||
## About |
|||
|
|||
### Related projects |
|||
|
|||
* [arr-diff](https://www.npmjs.com/package/arr-diff): Returns an array with only the unique values from the first array, by excluding all… [more](https://github.com/jonschlinkert/arr-diff) | [homepage](https://github.com/jonschlinkert/arr-diff "Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons.") |
|||
* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten "Recursively flatten an array or arrays. This is the fastest implementation of array flatten.") |
|||
* [arr-map](https://www.npmjs.com/package/arr-map): Faster, node.js focused alternative to JavaScript's native array map. | [homepage](https://github.com/jonschlinkert/arr-map "Faster, node.js focused alternative to JavaScript's native array map.") |
|||
* [arr-pluck](https://www.npmjs.com/package/arr-pluck): Retrieves the value of a specified property from all elements in the collection. | [homepage](https://github.com/jonschlinkert/arr-pluck "Retrieves the value of a specified property from all elements in the collection.") |
|||
* [arr-reduce](https://www.npmjs.com/package/arr-reduce): Fast array reduce that also loops over sparse elements. | [homepage](https://github.com/jonschlinkert/arr-reduce "Fast array reduce that also loops over sparse elements.") |
|||
* [arr-union](https://www.npmjs.com/package/arr-union): Combines a list of arrays, returning a single array with unique values, using strict equality… [more](https://github.com/jonschlinkert/arr-union) | [homepage](https://github.com/jonschlinkert/arr-union "Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons.") |
|||
|
|||
### Contributing |
|||
|
|||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). |
|||
|
|||
### Building docs |
|||
|
|||
_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_ |
|||
|
|||
To generate the readme and API documentation with [verb](https://github.com/verbose/verb): |
|||
|
|||
```sh |
|||
$ npm install -g verb verb-generate-readme && verb |
|||
``` |
|||
|
|||
### Running tests |
|||
|
|||
Install dev dependencies: |
|||
|
|||
```sh |
|||
$ npm install -d && npm test |
|||
``` |
|||
|
|||
### Author |
|||
|
|||
**Jon Schlinkert** |
|||
|
|||
* [github/jonschlinkert](https://github.com/jonschlinkert) |
|||
* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) |
|||
|
|||
### License |
|||
|
|||
Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). |
|||
Released under the [MIT license](https://github.com/jonschlinkert/array-unique/blob/master/LICENSE). |
|||
|
|||
*** |
|||
|
|||
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.28, on July 31, 2016._ |
@ -0,0 +1,43 @@ |
|||
/*! |
|||
* array-unique <https://github.com/jonschlinkert/array-unique>
|
|||
* |
|||
* Copyright (c) 2014-2015, Jon Schlinkert. |
|||
* Licensed under the MIT License. |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
module.exports = function unique(arr) { |
|||
if (!Array.isArray(arr)) { |
|||
throw new TypeError('array-unique expects an array.'); |
|||
} |
|||
|
|||
var len = arr.length; |
|||
var i = -1; |
|||
|
|||
while (i++ < len) { |
|||
var j = i + 1; |
|||
|
|||
for (; j < arr.length; ++j) { |
|||
if (arr[i] === arr[j]) { |
|||
arr.splice(j--, 1); |
|||
} |
|||
} |
|||
} |
|||
return arr; |
|||
}; |
|||
|
|||
module.exports.immutable = function uniqueImmutable(arr) { |
|||
if (!Array.isArray(arr)) { |
|||
throw new TypeError('array-unique expects an array.'); |
|||
} |
|||
|
|||
var arrLen = arr.length; |
|||
var newArr = new Array(arrLen); |
|||
|
|||
for (var i = 0; i < arrLen; i++) { |
|||
newArr[i] = arr[i]; |
|||
} |
|||
|
|||
return module.exports(newArr); |
|||
}; |
@ -0,0 +1,96 @@ |
|||
{ |
|||
"_from": "array-unique@^0.3.2", |
|||
"_id": "array-unique@0.3.2", |
|||
"_inBundle": false, |
|||
"_integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", |
|||
"_location": "/array-unique", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "range", |
|||
"registry": true, |
|||
"raw": "array-unique@^0.3.2", |
|||
"name": "array-unique", |
|||
"escapedName": "array-unique", |
|||
"rawSpec": "^0.3.2", |
|||
"saveSpec": null, |
|||
"fetchSpec": "^0.3.2" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/braces", |
|||
"/extglob", |
|||
"/micromatch", |
|||
"/nanomatch" |
|||
], |
|||
"_resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", |
|||
"_shasum": "a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428", |
|||
"_spec": "array-unique@^0.3.2", |
|||
"_where": "/home/rohan/git/chatto-spring/chatto/src/main/javascript/node_modules/micromatch", |
|||
"author": { |
|||
"name": "Jon Schlinkert", |
|||
"url": "https://github.com/jonschlinkert" |
|||
}, |
|||
"bugs": { |
|||
"url": "https://github.com/jonschlinkert/array-unique/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"deprecated": false, |
|||
"description": "Remove duplicate values from an array. Fastest ES5 implementation.", |
|||
"devDependencies": { |
|||
"array-uniq": "^1.0.2", |
|||
"benchmarked": "^0.1.3", |
|||
"gulp-format-md": "^0.1.9", |
|||
"mocha": "^2.5.3", |
|||
"should": "^10.0.0" |
|||
}, |
|||
"engines": { |
|||
"node": ">=0.10.0" |
|||
}, |
|||
"files": [ |
|||
"index.js", |
|||
"LICENSE", |
|||
"README.md" |
|||
], |
|||
"homepage": "https://github.com/jonschlinkert/array-unique", |
|||
"keywords": [ |
|||
"array", |
|||
"unique" |
|||
], |
|||
"license": "MIT", |
|||
"main": "index.js", |
|||
"name": "array-unique", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/jonschlinkert/array-unique.git" |
|||
}, |
|||
"scripts": { |
|||
"test": "mocha" |
|||
}, |
|||
"verb": { |
|||
"toc": false, |
|||
"layout": "default", |
|||
"tasks": [ |
|||
"readme" |
|||
], |
|||
"plugins": [ |
|||
"gulp-format-md" |
|||
], |
|||
"related": { |
|||
"list": [ |
|||
"arr-diff", |
|||
"arr-union", |
|||
"arr-flatten", |
|||
"arr-reduce", |
|||
"arr-map", |
|||
"arr-pluck" |
|||
] |
|||
}, |
|||
"reflinks": [ |
|||
"verb", |
|||
"verb-generate-readme" |
|||
], |
|||
"lint": { |
|||
"reflinks": true |
|||
} |
|||
}, |
|||
"version": "0.3.2" |
|||
} |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2015, Jon Schlinkert. |
|||
|
|||
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,73 @@ |
|||
# assign-symbols [![NPM version](https://badge.fury.io/js/assign-symbols.svg)](http://badge.fury.io/js/assign-symbols) |
|||
|
|||
> Assign the enumerable es6 Symbol properties from an object (or objects) to the first object passed on the arguments. Can be used as a supplement to other extend, assign or merge methods as a polyfill for the Symbols part of the es6 Object.assign method. |
|||
|
|||
From the [Mozilla Developer docs for Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol): |
|||
|
|||
> A symbol is a unique and immutable data type and may be used as an identifier for object properties. The symbol object is an implicit object wrapper for the symbol primitive data type. |
|||
|
|||
## Install |
|||
|
|||
Install with [npm](https://www.npmjs.com/) |
|||
|
|||
```sh |
|||
$ npm i assign-symbols --save |
|||
``` |
|||
|
|||
## Usage |
|||
|
|||
```js |
|||
var assignSymbols = require('assign-symbols'); |
|||
var obj = {}; |
|||
|
|||
var one = {}; |
|||
var symbolOne = Symbol('aaa'); |
|||
one[symbolOne] = 'bbb'; |
|||
|
|||
var two = {}; |
|||
var symbolTwo = Symbol('ccc'); |
|||
two[symbolTwo] = 'ddd'; |
|||
|
|||
assignSymbols(obj, one, two); |
|||
|
|||
console.log(obj[symbolOne]); |
|||
//=> 'bbb' |
|||
console.log(obj[symbolTwo]); |
|||
//=> 'ddd' |
|||
``` |
|||
|
|||
## Similar projects |
|||
|
|||
* [assign-deep](https://www.npmjs.com/package/assign-deep): Deeply assign the enumerable properties of source objects to a destination object. | [homepage](https://github.com/jonschlinkert/assign-deep) |
|||
* [clone-deep](https://www.npmjs.com/package/clone-deep): Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives. | [homepage](https://github.com/jonschlinkert/clone-deep) |
|||
* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow) |
|||
* [merge-deep](https://www.npmjs.com/package/merge-deep): Recursively merge values in a javascript object. | [homepage](https://github.com/jonschlinkert/merge-deep) |
|||
* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep) |
|||
|
|||
## Running tests |
|||
|
|||
Install dev dependencies: |
|||
|
|||
```sh |
|||
$ npm i -d && npm test |
|||
``` |
|||
|
|||
## Contributing |
|||
|
|||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/assign-symbols/issues/new). |
|||
|
|||
## Author |
|||
|
|||
**Jon Schlinkert** |
|||
|
|||
+ [github/jonschlinkert](https://github.com/jonschlinkert) |
|||
+ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) |
|||
|
|||
## License |
|||
|
|||
Copyright © 2015 Jon Schlinkert |
|||
Released under the MIT license. |
|||
|
|||
*** |
|||
|
|||
_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on November 06, 2015._ |
@ -0,0 +1,40 @@ |
|||
/*! |
|||
* assign-symbols <https://github.com/jonschlinkert/assign-symbols>
|
|||
* |
|||
* Copyright (c) 2015, Jon Schlinkert. |
|||
* Licensed under the MIT License. |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
module.exports = function(receiver, objects) { |
|||
if (receiver === null || typeof receiver === 'undefined') { |
|||
throw new TypeError('expected first argument to be an object.'); |
|||
} |
|||
|
|||
if (typeof objects === 'undefined' || typeof Symbol === 'undefined') { |
|||
return receiver; |
|||
} |
|||
|
|||
if (typeof Object.getOwnPropertySymbols !== 'function') { |
|||
return receiver; |
|||
} |
|||
|
|||
var isEnumerable = Object.prototype.propertyIsEnumerable; |
|||
var target = Object(receiver); |
|||
var len = arguments.length, i = 0; |
|||
|
|||
while (++i < len) { |
|||
var provider = Object(arguments[i]); |
|||
var names = Object.getOwnPropertySymbols(provider); |
|||
|
|||
for (var j = 0; j < names.length; j++) { |
|||
var key = names[j]; |
|||
|
|||
if (isEnumerable.call(provider, key)) { |
|||
target[key] = provider[key]; |
|||
} |
|||
} |
|||
} |
|||
return target; |
|||
}; |
@ -0,0 +1,71 @@ |
|||
{ |
|||
"_from": "assign-symbols@^1.0.0", |
|||
"_id": "assign-symbols@1.0.0", |
|||
"_inBundle": false, |
|||
"_integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", |
|||
"_location": "/assign-symbols", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "range", |
|||
"registry": true, |
|||
"raw": "assign-symbols@^1.0.0", |
|||
"name": "assign-symbols", |
|||
"escapedName": "assign-symbols", |
|||
"rawSpec": "^1.0.0", |
|||
"saveSpec": null, |
|||
"fetchSpec": "^1.0.0" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/extend-shallow" |
|||
], |
|||
"_resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", |
|||
"_shasum": "59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367", |
|||
"_spec": "assign-symbols@^1.0.0", |
|||
"_where": "/home/rohan/git/chatto-spring/chatto/src/main/javascript/node_modules/extend-shallow", |
|||
"author": { |
|||
"name": "Jon Schlinkert", |
|||
"url": "https://github.com/jonschlinkert" |
|||
}, |
|||
"bugs": { |
|||
"url": "https://github.com/jonschlinkert/assign-symbols/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"deprecated": false, |
|||
"description": "Assign the enumerable es6 Symbol properties from an object (or objects) to the first object passed on the arguments. Can be used as a supplement to other extend, assign or merge methods as a polyfill for the Symbols part of the es6 Object.assign method.", |
|||
"devDependencies": { |
|||
"mocha": "^3.0.0" |
|||
}, |
|||
"engines": { |
|||
"node": ">=0.10.0" |
|||
}, |
|||
"files": [ |
|||
"index.js" |
|||
], |
|||
"homepage": "https://github.com/jonschlinkert/assign-symbols", |
|||
"keywords": [ |
|||
"assign", |
|||
"symbols" |
|||
], |
|||
"license": "MIT", |
|||
"main": "index.js", |
|||
"name": "assign-symbols", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/jonschlinkert/assign-symbols.git" |
|||
}, |
|||
"scripts": { |
|||
"test": "mocha" |
|||
}, |
|||
"verb": { |
|||
"related": { |
|||
"list": [ |
|||
"assign-deep", |
|||
"mixin-deep", |
|||
"merge-deep", |
|||
"extend-shallow", |
|||
"clone-deep" |
|||
] |
|||
} |
|||
}, |
|||
"version": "1.0.0" |
|||
} |
@ -0,0 +1,230 @@ |
|||
At your option you may choose either of the following licenses: |
|||
|
|||
* The MIT License (MIT) |
|||
* The Apache License 2.0 (Apache-2.0) |
|||
|
|||
|
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2015 AJ ONeal |
|||
|
|||
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. |
|||
|
|||
|
|||
Apache License |
|||
Version 2.0, January 2004 |
|||
http://www.apache.org/licenses/ |
|||
|
|||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
|||
|
|||
1. Definitions. |
|||
|
|||
"License" shall mean the terms and conditions for use, reproduction, |
|||
and distribution as defined by Sections 1 through 9 of this document. |
|||
|
|||
"Licensor" shall mean the copyright owner or entity authorized by |
|||
the copyright owner that is granting the License. |
|||
|
|||
"Legal Entity" shall mean the union of the acting entity and all |
|||
other entities that control, are controlled by, or are under common |
|||
control with that entity. For the purposes of this definition, |
|||
"control" means (i) the power, direct or indirect, to cause the |
|||
direction or management of such entity, whether by contract or |
|||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
|||
outstanding shares, or (iii) beneficial ownership of such entity. |
|||
|
|||
"You" (or "Your") shall mean an individual or Legal Entity |
|||
exercising permissions granted by this License. |
|||
|
|||
"Source" form shall mean the preferred form for making modifications, |
|||
including but not limited to software source code, documentation |
|||
source, and configuration files. |
|||
|
|||
"Object" form shall mean any form resulting from mechanical |
|||
transformation or translation of a Source form, including but |
|||
not limited to compiled object code, generated documentation, |
|||
and conversions to other media types. |
|||
|
|||
"Work" shall mean the work of authorship, whether in Source or |
|||
Object form, made available under the License, as indicated by a |
|||
copyright notice that is included in or attached to the work |
|||
(an example is provided in the Appendix below). |
|||
|
|||
"Derivative Works" shall mean any work, whether in Source or Object |
|||
form, that is based on (or derived from) the Work and for which the |
|||
editorial revisions, annotations, elaborations, or other modifications |
|||
represent, as a whole, an original work of authorship. For the purposes |
|||
of this License, Derivative Works shall not include works that remain |
|||
separable from, or merely link (or bind by name) to the interfaces of, |
|||
the Work and Derivative Works thereof. |
|||
|
|||
"Contribution" shall mean any work of authorship, including |
|||
the original version of the Work and any modifications or additions |
|||
to that Work or Derivative Works thereof, that is intentionally |
|||
submitted to Licensor for inclusion in the Work by the copyright owner |
|||
or by an individual or Legal Entity authorized to submit on behalf of |
|||
the copyright owner. For the purposes of this definition, "submitted" |
|||
means any form of electronic, verbal, or written communication sent |
|||
to the Licensor or its representatives, including but not limited to |
|||
communication on electronic mailing lists, source code control systems, |
|||
and issue tracking systems that are managed by, or on behalf of, the |
|||
Licensor for the purpose of discussing and improving the Work, but |
|||
excluding communication that is conspicuously marked or otherwise |
|||
designated in writing by the copyright owner as "Not a Contribution." |
|||
|
|||
"Contributor" shall mean Licensor and any individual or Legal Entity |
|||
on behalf of whom a Contribution has been received by Licensor and |
|||
subsequently incorporated within the Work. |
|||
|
|||
2. Grant of Copyright License. Subject to the terms and conditions of |
|||
this License, each Contributor hereby grants to You a perpetual, |
|||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|||
copyright license to reproduce, prepare Derivative Works of, |
|||
publicly display, publicly perform, sublicense, and distribute the |
|||
Work and such Derivative Works in Source or Object form. |
|||
|
|||
3. Grant of Patent License. Subject to the terms and conditions of |
|||
this License, each Contributor hereby grants to You a perpetual, |
|||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|||
(except as stated in this section) patent license to make, have made, |
|||
use, offer to sell, sell, import, and otherwise transfer the Work, |
|||
where such license applies only to those patent claims licensable |
|||
by such Contributor that are necessarily infringed by their |
|||
Contribution(s) alone or by combination of their Contribution(s) |
|||
with the Work to which such Contribution(s) was submitted. If You |
|||
institute patent litigation against any entity (including a |
|||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
|||
or a Contribution incorporated within the Work constitutes direct |
|||
or contributory patent infringement, then any patent licenses |
|||
granted to You under this License for that Work shall terminate |
|||
as of the date such litigation is filed. |
|||
|
|||
4. Redistribution. You may reproduce and distribute copies of the |
|||
Work or Derivative Works thereof in any medium, with or without |
|||
modifications, and in Source or Object form, provided that You |
|||
meet the following conditions: |
|||
|
|||
(a) You must give any other recipients of the Work or |
|||
Derivative Works a copy of this License; and |
|||
|
|||
(b) You must cause any modified files to carry prominent notices |
|||
stating that You changed the files; and |
|||
|
|||
(c) You must retain, in the Source form of any Derivative Works |
|||
that You distribute, all copyright, patent, trademark, and |
|||
attribution notices from the Source form of the Work, |
|||
excluding those notices that do not pertain to any part of |
|||
the Derivative Works; and |
|||
|
|||
(d) If the Work includes a "NOTICE" text file as part of its |
|||
distribution, then any Derivative Works that You distribute must |
|||
include a readable copy of the attribution notices contained |
|||
within such NOTICE file, excluding those notices that do not |
|||
pertain to any part of the Derivative Works, in at least one |
|||
of the following places: within a NOTICE text file distributed |
|||
as part of the Derivative Works; within the Source form or |
|||
documentation, if provided along with the Derivative Works; or, |
|||
within a display generated by the Derivative Works, if and |
|||
wherever such third-party notices normally appear. The contents |
|||
of the NOTICE file are for informational purposes only and |
|||
do not modify the License. You may add Your own attribution |
|||
notices within Derivative Works that You distribute, alongside |
|||
or as an addendum to the NOTICE text from the Work, provided |
|||
that such additional attribution notices cannot be construed |
|||
as modifying the License. |
|||
|
|||
You may add Your own copyright statement to Your modifications and |
|||
may provide additional or different license terms and conditions |
|||
for use, reproduction, or distribution of Your modifications, or |
|||
for any such Derivative Works as a whole, provided Your use, |
|||
reproduction, and distribution of the Work otherwise complies with |
|||
the conditions stated in this License. |
|||
|
|||
5. Submission of Contributions. Unless You explicitly state otherwise, |
|||
any Contribution intentionally submitted for inclusion in the Work |
|||
by You to the Licensor shall be under the terms and conditions of |
|||
this License, without any additional terms or conditions. |
|||
Notwithstanding the above, nothing herein shall supersede or modify |
|||
the terms of any separate license agreement you may have executed |
|||
with Licensor regarding such Contributions. |
|||
|
|||
6. Trademarks. This License does not grant permission to use the trade |
|||
names, trademarks, service marks, or product names of the Licensor, |
|||
except as required for reasonable and customary use in describing the |
|||
origin of the Work and reproducing the content of the NOTICE file. |
|||
|
|||
7. Disclaimer of Warranty. Unless required by applicable law or |
|||
agreed to in writing, Licensor provides the Work (and each |
|||
Contributor provides its Contributions) on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
|||
implied, including, without limitation, any warranties or conditions |
|||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
|||
PARTICULAR PURPOSE. You are solely responsible for determining the |
|||
appropriateness of using or redistributing the Work and assume any |
|||
risks associated with Your exercise of permissions under this License. |
|||
|
|||
8. Limitation of Liability. In no event and under no legal theory, |
|||
whether in tort (including negligence), contract, or otherwise, |
|||
unless required by applicable law (such as deliberate and grossly |
|||
negligent acts) or agreed to in writing, shall any Contributor be |
|||
liable to You for damages, including any direct, indirect, special, |
|||
incidental, or consequential damages of any character arising as a |
|||
result of this License or out of the use or inability to use the |
|||
Work (including but not limited to damages for loss of goodwill, |
|||
work stoppage, computer failure or malfunction, or any and all |
|||
other commercial damages or losses), even if such Contributor |
|||
has been advised of the possibility of such damages. |
|||
|
|||
9. Accepting Warranty or Additional Liability. While redistributing |
|||
the Work or Derivative Works thereof, You may choose to offer, |
|||
and charge a fee for, acceptance of support, warranty, indemnity, |
|||
or other liability obligations and/or rights consistent with this |
|||
License. However, in accepting such obligations, You may act only |
|||
on Your own behalf and on Your sole responsibility, not on behalf |
|||
of any other Contributor, and only if You agree to indemnify, |
|||
defend, and hold each Contributor harmless for any liability |
|||
incurred by, or claims asserted against, such Contributor by reason |
|||
of your accepting any such warranty or additional liability. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
APPENDIX: How to apply the Apache License to your work. |
|||
|
|||
To apply the Apache License to your work, attach the following |
|||
boilerplate notice, with the fields enclosed by brackets "{}" |
|||
replaced with your own identifying information. (Don't include |
|||
the brackets!) The text should be enclosed in the appropriate |
|||
comment syntax for the file format. We also recommend that a |
|||
file or class name and description of purpose be included on the |
|||
same "printed page" as the copyright notice for easier |
|||
identification within third-party archives. |
|||
|
|||
Copyright 2015 AJ ONeal |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
@ -0,0 +1,319 @@ |
|||
Creative Commons Legal Code |
|||
|
|||
Attribution 3.0 Unported |
|||
|
|||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE |
|||
LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN |
|||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS |
|||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES |
|||
REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR |
|||
DAMAGES RESULTING FROM ITS USE. |
|||
|
|||
License |
|||
|
|||
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE |
|||
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY |
|||
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS |
|||
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. |
|||
|
|||
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE |
|||
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY |
|||
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS |
|||
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND |
|||
CONDITIONS. |
|||
|
|||
1. Definitions |
|||
|
|||
a. "Adaptation" means a work based upon the Work, or upon the Work and |
|||
other pre-existing works, such as a translation, adaptation, |
|||
derivative work, arrangement of music or other alterations of a |
|||
literary or artistic work, or phonogram or performance and includes |
|||
cinematographic adaptations or any other form in which the Work may be |
|||
recast, transformed, or adapted including in any form recognizably |
|||
derived from the original, except that a work that constitutes a |
|||
Collection will not be considered an Adaptation for the purpose of |
|||
this License. For the avoidance of doubt, where the Work is a musical |
|||
work, performance or phonogram, the synchronization of the Work in |
|||
timed-relation with a moving image ("synching") will be considered an |
|||
Adaptation for the purpose of this License. |
|||
b. "Collection" means a collection of literary or artistic works, such as |
|||
encyclopedias and anthologies, or performances, phonograms or |
|||
broadcasts, or other works or subject matter other than works listed |
|||
in Section 1(f) below, which, by reason of the selection and |
|||
arrangement of their contents, constitute intellectual creations, in |
|||
which the Work is included in its entirety in unmodified form along |
|||
with one or more other contributions, each constituting separate and |
|||
independent works in themselves, which together are assembled into a |
|||
collective whole. A work that constitutes a Collection will not be |
|||
considered an Adaptation (as defined above) for the purposes of this |
|||
License. |
|||
c. "Distribute" means to make available to the public the original and |
|||
copies of the Work or Adaptation, as appropriate, through sale or |
|||
other transfer of ownership. |
|||
d. "Licensor" means the individual, individuals, entity or entities that |
|||
offer(s) the Work under the terms of this License. |
|||
e. "Original Author" means, in the case of a literary or artistic work, |
|||
the individual, individuals, entity or entities who created the Work |
|||
or if no individual or entity can be identified, the publisher; and in |
|||
addition (i) in the case of a performance the actors, singers, |
|||
musicians, dancers, and other persons who act, sing, deliver, declaim, |
|||
play in, interpret or otherwise perform literary or artistic works or |
|||
expressions of folklore; (ii) in the case of a phonogram the producer |
|||
being the person or legal entity who first fixes the sounds of a |
|||
performance or other sounds; and, (iii) in the case of broadcasts, the |
|||
organization that transmits the broadcast. |
|||
f. "Work" means the literary and/or artistic work offered under the terms |
|||
of this License including without limitation any production in the |
|||
literary, scientific and artistic domain, whatever may be the mode or |
|||
form of its expression including digital form, such as a book, |
|||
pamphlet and other writing; a lecture, address, sermon or other work |
|||
of the same nature; a dramatic or dramatico-musical work; a |
|||
choreographic work or entertainment in dumb show; a musical |
|||
composition with or without words; a cinematographic work to which are |
|||
assimilated works expressed by a process analogous to cinematography; |
|||
a work of drawing, painting, architecture, sculpture, engraving or |
|||
lithography; a photographic work to which are assimilated works |
|||
expressed by a process analogous to photography; a work of applied |
|||
art; an illustration, map, plan, sketch or three-dimensional work |
|||
relative to geography, topography, architecture or science; a |
|||
performance; a broadcast; a phonogram; a compilation of data to the |
|||
extent it is protected as a copyrightable work; or a work performed by |
|||
a variety or circus performer to the extent it is not otherwise |
|||
considered a literary or artistic work. |
|||
g. "You" means an individual or entity exercising rights under this |
|||
License who has not previously violated the terms of this License with |
|||
respect to the Work, or who has received express permission from the |
|||
Licensor to exercise rights under this License despite a previous |
|||
violation. |
|||
h. "Publicly Perform" means to perform public recitations of the Work and |
|||
to communicate to the public those public recitations, by any means or |
|||
process, including by wire or wireless means or public digital |
|||
performances; to make available to the public Works in such a way that |
|||
members of the public may access these Works from a place and at a |
|||
place individually chosen by them; to perform the Work to the public |
|||
by any means or process and the communication to the public of the |
|||
performances of the Work, including by public digital performance; to |
|||
broadcast and rebroadcast the Work by any means including signs, |
|||
sounds or images. |
|||
i. "Reproduce" means to make copies of the Work by any means including |
|||
without limitation by sound or visual recordings and the right of |
|||
fixation and reproducing fixations of the Work, including storage of a |
|||
protected performance or phonogram in digital form or other electronic |
|||
medium. |
|||
|
|||
2. Fair Dealing Rights. Nothing in this License is intended to reduce, |
|||
limit, or restrict any uses free from copyright or rights arising from |
|||
limitations or exceptions that are provided for in connection with the |
|||
copyright protection under copyright law or other applicable laws. |
|||
|
|||
3. License Grant. Subject to the terms and conditions of this License, |
|||
Licensor hereby grants You a worldwide, royalty-free, non-exclusive, |
|||
perpetual (for the duration of the applicable copyright) license to |
|||
exercise the rights in the Work as stated below: |
|||
|
|||
a. to Reproduce the Work, to incorporate the Work into one or more |
|||
Collections, and to Reproduce the Work as incorporated in the |
|||
Collections; |
|||
b. to create and Reproduce Adaptations provided that any such Adaptation, |
|||
including any translation in any medium, takes reasonable steps to |
|||
clearly label, demarcate or otherwise identify that changes were made |
|||
to the original Work. For example, a translation could be marked "The |
|||
original work was translated from English to Spanish," or a |
|||
modification could indicate "The original work has been modified."; |
|||
c. to Distribute and Publicly Perform the Work including as incorporated |
|||
in Collections; and, |
|||
d. to Distribute and Publicly Perform Adaptations. |
|||
e. For the avoidance of doubt: |
|||
|
|||
i. Non-waivable Compulsory License Schemes. In those jurisdictions in |
|||
which the right to collect royalties through any statutory or |
|||
compulsory licensing scheme cannot be waived, the Licensor |
|||
reserves the exclusive right to collect such royalties for any |
|||
exercise by You of the rights granted under this License; |
|||
ii. Waivable Compulsory License Schemes. In those jurisdictions in |
|||
which the right to collect royalties through any statutory or |
|||
compulsory licensing scheme can be waived, the Licensor waives the |
|||
exclusive right to collect such royalties for any exercise by You |
|||
of the rights granted under this License; and, |
|||
iii. Voluntary License Schemes. The Licensor waives the right to |
|||
collect royalties, whether individually or, in the event that the |
|||
Licensor is a member of a collecting society that administers |
|||
voluntary licensing schemes, via that society, from any exercise |
|||
by You of the rights granted under this License. |
|||
|
|||
The above rights may be exercised in all media and formats whether now |
|||
known or hereafter devised. The above rights include the right to make |
|||
such modifications as are technically necessary to exercise the rights in |
|||
other media and formats. Subject to Section 8(f), all rights not expressly |
|||
granted by Licensor are hereby reserved. |
|||
|
|||
4. Restrictions. The license granted in Section 3 above is expressly made |
|||
subject to and limited by the following restrictions: |
|||
|
|||
a. You may Distribute or Publicly Perform the Work only under the terms |
|||
of this License. You must include a copy of, or the Uniform Resource |
|||
Identifier (URI) for, this License with every copy of the Work You |
|||
Distribute or Publicly Perform. You may not offer or impose any terms |
|||
on the Work that restrict the terms of this License or the ability of |
|||
the recipient of the Work to exercise the rights granted to that |
|||
recipient under the terms of the License. You may not sublicense the |
|||
Work. You must keep intact all notices that refer to this License and |
|||
to the disclaimer of warranties with every copy of the Work You |
|||
Distribute or Publicly Perform. When You Distribute or Publicly |
|||
Perform the Work, You may not impose any effective technological |
|||
measures on the Work that restrict the ability of a recipient of the |
|||
Work from You to exercise the rights granted to that recipient under |
|||
the terms of the License. This Section 4(a) applies to the Work as |
|||
incorporated in a Collection, but this does not require the Collection |
|||
apart from the Work itself to be made subject to the terms of this |
|||
License. If You create a Collection, upon notice from any Licensor You |
|||
must, to the extent practicable, remove from the Collection any credit |
|||
as required by Section 4(b), as requested. If You create an |
|||
Adaptation, upon notice from any Licensor You must, to the extent |
|||
practicable, remove from the Adaptation any credit as required by |
|||
Section 4(b), as requested. |
|||
b. If You Distribute, or Publicly Perform the Work or any Adaptations or |
|||
Collections, You must, unless a request has been made pursuant to |
|||
Section 4(a), keep intact all copyright notices for the Work and |
|||
provide, reasonable to the medium or means You are utilizing: (i) the |
|||
name of the Original Author (or pseudonym, if applicable) if supplied, |
|||
and/or if the Original Author and/or Licensor designate another party |
|||
or parties (e.g., a sponsor institute, publishing entity, journal) for |
|||
attribution ("Attribution Parties") in Licensor's copyright notice, |
|||
terms of service or by other reasonable means, the name of such party |
|||
or parties; (ii) the title of the Work if supplied; (iii) to the |
|||
extent reasonably practicable, the URI, if any, that Licensor |
|||
specifies to be associated with the Work, unless such URI does not |
|||
refer to the copyright notice or licensing information for the Work; |
|||
and (iv) , consistent with Section 3(b), in the case of an Adaptation, |
|||
a credit identifying the use of the Work in the Adaptation (e.g., |
|||
"French translation of the Work by Original Author," or "Screenplay |
|||
based on original Work by Original Author"). The credit required by |
|||
this Section 4 (b) may be implemented in any reasonable manner; |
|||
provided, however, that in the case of a Adaptation or Collection, at |
|||
a minimum such credit will appear, if a credit for all contributing |
|||
authors of the Adaptation or Collection appears, then as part of these |
|||
credits and in a manner at least as prominent as the credits for the |
|||
other contributing authors. For the avoidance of doubt, You may only |
|||
use the credit required by this Section for the purpose of attribution |
|||
in the manner set out above and, by exercising Your rights under this |
|||
License, You may not implicitly or explicitly assert or imply any |
|||
connection with, sponsorship or endorsement by the Original Author, |
|||
Licensor and/or Attribution Parties, as appropriate, of You or Your |
|||
use of the Work, without the separate, express prior written |
|||
permission of the Original Author, Licensor and/or Attribution |
|||
Parties. |
|||
c. Except as otherwise agreed in writing by the Licensor or as may be |
|||
otherwise permitted by applicable law, if You Reproduce, Distribute or |
|||
Publicly Perform the Work either by itself or as part of any |
|||
Adaptations or Collections, You must not distort, mutilate, modify or |
|||
take other derogatory action in relation to the Work which would be |
|||
prejudicial to the Original Author's honor or reputation. Licensor |
|||
agrees that in those jurisdictions (e.g. Japan), in which any exercise |
|||
of the right granted in Section 3(b) of this License (the right to |
|||
make Adaptations) would be deemed to be a distortion, mutilation, |
|||
modification or other derogatory action prejudicial to the Original |
|||
Author's honor and reputation, the Licensor will waive or not assert, |
|||
as appropriate, this Section, to the fullest extent permitted by the |
|||
applicable national law, to enable You to reasonably exercise Your |
|||
right under Section 3(b) of this License (right to make Adaptations) |
|||
but not otherwise. |
|||
|
|||
5. Representations, Warranties and Disclaimer |
|||
|
|||
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR |
|||
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY |
|||
KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, |
|||
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF |
|||
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, |
|||
WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION |
|||
OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. |
|||
|
|||
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE |
|||
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR |
|||
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES |
|||
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS |
|||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. |
|||
|
|||
7. Termination |
|||
|
|||
a. This License and the rights granted hereunder will terminate |
|||
automatically upon any breach by You of the terms of this License. |
|||
Individuals or entities who have received Adaptations or Collections |
|||
from You under this License, however, will not have their licenses |
|||
terminated provided such individuals or entities remain in full |
|||
compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will |
|||
survive any termination of this License. |
|||
b. Subject to the above terms and conditions, the license granted here is |
|||
perpetual (for the duration of the applicable copyright in the Work). |
|||
Notwithstanding the above, Licensor reserves the right to release the |
|||
Work under different license terms or to stop distributing the Work at |
|||
any time; provided, however that any such election will not serve to |
|||
withdraw this License (or any other license that has been, or is |
|||
required to be, granted under the terms of this License), and this |
|||
License will continue in full force and effect unless terminated as |
|||
stated above. |
|||
|
|||
8. Miscellaneous |
|||
|
|||
a. Each time You Distribute or Publicly Perform the Work or a Collection, |
|||
the Licensor offers to the recipient a license to the Work on the same |
|||
terms and conditions as the license granted to You under this License. |
|||
b. Each time You Distribute or Publicly Perform an Adaptation, Licensor |
|||
offers to the recipient a license to the original Work on the same |
|||
terms and conditions as the license granted to You under this License. |
|||
c. If any provision of this License is invalid or unenforceable under |
|||
applicable law, it shall not affect the validity or enforceability of |
|||
the remainder of the terms of this License, and without further action |
|||
by the parties to this agreement, such provision shall be reformed to |
|||
the minimum extent necessary to make such provision valid and |
|||
enforceable. |
|||
d. No term or provision of this License shall be deemed waived and no |
|||
breach consented to unless such waiver or consent shall be in writing |
|||
and signed by the party to be charged with such waiver or consent. |
|||
e. This License constitutes the entire agreement between the parties with |
|||
respect to the Work licensed here. There are no understandings, |
|||
agreements or representations with respect to the Work not specified |
|||
here. Licensor shall not be bound by any additional provisions that |
|||
may appear in any communication from You. This License may not be |
|||
modified without the mutual written agreement of the Licensor and You. |
|||
f. The rights granted under, and the subject matter referenced, in this |
|||
License were drafted utilizing the terminology of the Berne Convention |
|||
for the Protection of Literary and Artistic Works (as amended on |
|||
September 28, 1979), the Rome Convention of 1961, the WIPO Copyright |
|||
Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 |
|||
and the Universal Copyright Convention (as revised on July 24, 1971). |
|||
These rights and subject matter take effect in the relevant |
|||
jurisdiction in which the License terms are sought to be enforced |
|||
according to the corresponding provisions of the implementation of |
|||
those treaty provisions in the applicable national law. If the |
|||
standard suite of rights granted under applicable copyright law |
|||
includes additional rights not granted under this License, such |
|||
additional rights are deemed to be included in the License; this |
|||
License is not intended to restrict the license of any rights under |
|||
applicable law. |
|||
|
|||
|
|||
Creative Commons Notice |
|||
|
|||
Creative Commons is not a party to this License, and makes no warranty |
|||
whatsoever in connection with the Work. Creative Commons will not be |
|||
liable to You or any party on any legal theory for any damages |
|||
whatsoever, including without limitation any general, special, |
|||
incidental or consequential damages arising in connection to this |
|||
license. Notwithstanding the foregoing two (2) sentences, if Creative |
|||
Commons has expressly identified itself as the Licensor hereunder, it |
|||
shall have all rights and obligations of Licensor. |
|||
|
|||
Except for the limited purpose of indicating to the public that the |
|||
Work is licensed under the CCPL, Creative Commons does not authorize |
|||
the use by either party of the trademark "Creative Commons" or any |
|||
related trademark or logo of Creative Commons without the prior |
|||
written consent of Creative Commons. Any permitted use will be in |
|||
compliance with Creative Commons' then-current trademark usage |
|||
guidelines, as may be published on its website or otherwise made |
|||
available upon request from time to time. For the avoidance of doubt, |
|||
this trademark restriction does not form part of this License. |
|||
|
|||
Creative Commons may be contacted at http://creativecommons.org/. |
@ -0,0 +1,49 @@ |
|||
atob |
|||
=== |
|||
|
|||
| **atob** |
|||
| [btoa](https://git.coolaj86.com/coolaj86/btoa.js) |
|||
| [unibabel.js](https://git.coolaj86.com/coolaj86/unibabel.js) |
|||
| Sponsored by [ppl](https://ppl.family) |
|||
|
|||
Uses `Buffer` to emulate the exact functionality of the browser's atob. |
|||
|
|||
Note: Unicode may be handled incorrectly (like the browser). |
|||
|
|||
It turns base64-encoded <strong>a</strong>scii data back **to** <strong>b</strong>inary. |
|||
|
|||
```javascript |
|||
(function () { |
|||
"use strict"; |
|||
|
|||
var atob = require('atob'); |
|||
var b64 = "SGVsbG8sIFdvcmxkIQ=="; |
|||
var bin = atob(b64); |
|||
|
|||
console.log(bin); // "Hello, World!" |
|||
}()); |
|||
``` |
|||
|
|||
### Need Unicode and Binary Support in the Browser? |
|||
|
|||
Check out [unibabel.js](https://git.coolaj86.com/coolaj86/unibabel.js) |
|||
|
|||
Changelog |
|||
======= |
|||
|
|||
* v2.1.0 address a few issues and PRs, update URLs |
|||
* v2.0.0 provide browser version for ios web workers |
|||
* v1.2.0 provide (empty) browser version |
|||
* v1.1.3 add MIT license |
|||
* v1.1.2 node only |
|||
|
|||
LICENSE |
|||
======= |
|||
|
|||
Code copyright 2012-2018 AJ ONeal |
|||
|
|||
Dual-licensed MIT and Apache-2.0 |
|||
|
|||
Docs copyright 2012-2018 AJ ONeal |
|||
|
|||
Docs released under [Creative Commons](https://git.coolaj86.com/coolaj86/atob.js/blob/master/LICENSE.DOCS). |
@ -0,0 +1,6 @@ |
|||
#!/usr/bin/env node
|
|||
'use strict'; |
|||
|
|||
var atob = require('../node-atob'); |
|||
var str = process.argv[2]; |
|||
console.log(atob(str)); |
@ -0,0 +1,24 @@ |
|||
{ |
|||
"name": "atob", |
|||
"description": "atob for isomorphic environments", |
|||
"main": "browser-atob.js", |
|||
"authors": [ |
|||
"AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com)" |
|||
], |
|||
"license": "(MIT OR Apache-2.0)", |
|||
"keywords": [ |
|||
"atob", |
|||
"browser" |
|||
], |
|||
"homepage": "https://github.com/node-browser-compat/atob", |
|||
"moduleType": [ |
|||
"globals" |
|||
], |
|||
"ignore": [ |
|||
"**/.*", |
|||
"node_modules", |
|||
"bower_components", |
|||
"test", |
|||
"tests" |
|||
] |
|||
} |
@ -0,0 +1,44 @@ |
|||
(function (w) { |
|||
"use strict"; |
|||
|
|||
function findBest(atobNative) { |
|||
// normal window
|
|||
if ('function' === typeof atobNative) { return atobNative; } |
|||
|
|||
|
|||
// browserify (web worker)
|
|||
if ('function' === typeof Buffer) { |
|||
return function atobBrowserify(a) { |
|||
//!! Deliberately using an API that's deprecated in node.js because
|
|||
//!! this file is for browsers and we expect them to cope with it.
|
|||
//!! Discussion: github.com/node-browser-compat/atob/pull/9
|
|||
return new Buffer(a, 'base64').toString('binary'); |
|||
}; |
|||
} |
|||
|
|||
// ios web worker with base64js
|
|||
if ('object' === typeof w.base64js) { |
|||
// bufferToBinaryString
|
|||
// https://git.coolaj86.com/coolaj86/unibabel.js/blob/master/index.js#L50
|
|||
return function atobWebWorker_iOS(a) { |
|||
var buf = w.base64js.b64ToByteArray(a); |
|||
return Array.prototype.map.call(buf, function (ch) { |
|||
return String.fromCharCode(ch); |
|||
}).join(''); |
|||
}; |
|||
} |
|||
|
|||
return function () { |
|||
// ios web worker without base64js
|
|||
throw new Error("You're probably in an old browser or an iOS webworker." + |
|||
" It might help to include beatgammit's base64-js."); |
|||
}; |
|||
} |
|||
|
|||
var atobBest = findBest(w.atob); |
|||
w.atob = atobBest; |
|||
|
|||
if ((typeof module === 'object') && module && module.exports) { |
|||
module.exports = atobBest; |
|||
} |
|||
}(window)); |
@ -0,0 +1,7 @@ |
|||
"use strict"; |
|||
|
|||
function atob(str) { |
|||
return Buffer.from(str, 'base64').toString('binary'); |
|||
} |
|||
|
|||
module.exports = atob.atob = atob; |
@ -0,0 +1,53 @@ |
|||
{ |
|||
"_from": "atob@^2.1.1", |
|||
"_id": "atob@2.1.2", |
|||
"_inBundle": false, |
|||
"_integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", |
|||
"_location": "/atob", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "range", |
|||
"registry": true, |
|||
"raw": "atob@^2.1.1", |
|||
"name": "atob", |
|||
"escapedName": "atob", |
|||
"rawSpec": "^2.1.1", |
|||
"saveSpec": null, |
|||
"fetchSpec": "^2.1.1" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/source-map-resolve" |
|||
], |
|||
"_resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", |
|||
"_shasum": "6d9517eb9e030d2436666651e86bd9f6f13533c9", |
|||
"_spec": "atob@^2.1.1", |
|||
"_where": "/home/rohan/git/chatto-spring/chatto/src/main/javascript/node_modules/source-map-resolve", |
|||
"author": { |
|||
"name": "AJ ONeal", |
|||
"email": "coolaj86@gmail.com", |
|||
"url": "https://coolaj86.com" |
|||
}, |
|||
"bin": { |
|||
"atob": "bin/atob.js" |
|||
}, |
|||
"browser": "browser-atob.js", |
|||
"bundleDependencies": false, |
|||
"deprecated": false, |
|||
"description": "atob for Node.JS and Linux / Mac / Windows CLI (it's a one-liner)", |
|||
"engines": { |
|||
"node": ">= 4.5.0" |
|||
}, |
|||
"homepage": "https://git.coolaj86.com/coolaj86/atob.js.git", |
|||
"keywords": [ |
|||
"atob", |
|||
"browser" |
|||
], |
|||
"license": "(MIT OR Apache-2.0)", |
|||
"main": "node-atob.js", |
|||
"name": "atob", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git://git.coolaj86.com/coolaj86/atob.js.git" |
|||
}, |
|||
"version": "2.1.2" |
|||
} |
@ -0,0 +1,18 @@ |
|||
(function () { |
|||
"use strict"; |
|||
|
|||
var atob = require('.'); |
|||
var encoded = "SGVsbG8sIFdvcmxkIQ==" |
|||
var unencoded = "Hello, World!"; |
|||
/* |
|||
, encoded = "SGVsbG8sIBZM" |
|||
, unencoded = "Hello, 世界" |
|||
*/ |
|||
|
|||
if (unencoded !== atob(encoded)) { |
|||
console.log('[FAIL]', unencoded, atob(encoded)); |
|||
return; |
|||
} |
|||
|
|||
console.log('[PASS] all tests pass'); |
|||
}()); |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2015-2017, Jon Schlinkert. |
|||
|
|||
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,491 @@ |
|||
<p align="center"> |
|||
<a href="https://github.com/node-base/base"> |
|||
<img height="250" width="250" src="https://raw.githubusercontent.com/node-base/base/master/docs/logo.png"> |
|||
</a> |
|||
</p> |
|||
|
|||
# base [![NPM version](https://img.shields.io/npm/v/base.svg?style=flat)](https://www.npmjs.com/package/base) [![NPM monthly downloads](https://img.shields.io/npm/dm/base.svg?style=flat)](https://npmjs.org/package/base) [![NPM total downloads](https://img.shields.io/npm/dt/base.svg?style=flat)](https://npmjs.org/package/base) [![Linux Build Status](https://img.shields.io/travis/node-base/base.svg?style=flat&label=Travis)](https://travis-ci.org/node-base/base) |
|||
|
|||
> base is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting with a handful of common methods, like `set`, `get`, `del` and `use`. |
|||
|
|||
## Install |
|||
|
|||
Install with [npm](https://www.npmjs.com/): |
|||
|
|||
```sh |
|||
$ npm install --save base |
|||
``` |
|||
|
|||
## What is Base? |
|||
|
|||
Base is a framework for rapidly creating high quality node.js applications, using plugins like building blocks. |
|||
|
|||
### Guiding principles |
|||
|
|||
The core team follows these principles to help guide API decisions: |
|||
|
|||
* **Compact API surface**: The smaller the API surface, the easier the library will be to learn and use. |
|||
* **Easy to extend**: Implementors can use any npm package, and write plugins in pure JavaScript. If you're building complex apps, Base simplifies inheritance. |
|||
* **Easy to test**: No special setup should be required to unit test `Base` or base plugins |
|||
|
|||
### Minimal API surface |
|||
|
|||
[The API](#api) was designed to provide only the minimum necessary functionality for creating a useful application, with or without [plugins](#plugins). |
|||
|
|||
**Base core** |
|||
|
|||
Base itself ships with only a handful of [useful methods](#api), such as: |
|||
|
|||
* `.set`: for setting values on the instance |
|||
* `.get`: for getting values from the instance |
|||
* `.has`: to check if a property exists on the instance |
|||
* `.define`: for setting non-enumerable values on the instance |
|||
* `.use`: for adding plugins |
|||
|
|||
**Be generic** |
|||
|
|||
When deciding on method to add or remove, we try to answer these questions: |
|||
|
|||
1. Will all or most Base applications need this method? |
|||
2. Will this method encourage practices or enforce conventions that are beneficial to implementors? |
|||
3. Can or should this be done in a plugin instead? |
|||
|
|||
### Composability |
|||
|
|||
**Plugin system** |
|||
|
|||
It couldn't be easier to extend Base with any features or custom functionality you can think of. |
|||
|
|||
Base plugins are just functions that take an instance of `Base`: |
|||
|
|||
```js |
|||
var base = new Base(); |
|||
|
|||
function plugin(base) { |
|||
// do plugin stuff, in pure JavaScript |
|||
} |
|||
// use the plugin |
|||
base.use(plugin); |
|||
``` |
|||
|
|||
**Inheritance** |
|||
|
|||
Easily inherit Base using `.extend`: |
|||
|
|||
```js |
|||
var Base = require('base'); |
|||
|
|||
function MyApp() { |
|||
Base.call(this); |
|||
} |
|||
Base.extend(MyApp); |
|||
|
|||
var app = new MyApp(); |
|||
app.set('a', 'b'); |
|||
app.get('a'); |
|||
//=> 'b'; |
|||
``` |
|||
|
|||
**Inherit or instantiate with a namespace** |
|||
|
|||
By default, the `.get`, `.set` and `.has` methods set and get values from the root of the `base` instance. You can customize this using the `.namespace` method exposed on the exported function. For example: |
|||
|
|||
```js |
|||
var Base = require('base'); |
|||
// get and set values on the `base.cache` object |
|||
var base = Base.namespace('cache'); |
|||
|
|||
var app = base(); |
|||
app.set('foo', 'bar'); |
|||
console.log(app.cache.foo); |
|||
//=> 'bar' |
|||
``` |
|||
|
|||
## API |
|||
|
|||
**Usage** |
|||
|
|||
```js |
|||
var Base = require('base'); |
|||
var app = new Base(); |
|||
app.set('foo', 'bar'); |
|||
console.log(app.foo); |
|||
//=> 'bar' |
|||
``` |
|||
|
|||
### [Base](index.js#L44) |
|||
|
|||
Create an instance of `Base` with the given `config` and `options`. |
|||
|
|||
**Params** |
|||
|
|||
* `config` **{Object}**: If supplied, this object is passed to [cache-base](https://github.com/jonschlinkert/cache-base) to merge onto the the instance upon instantiation. |
|||
* `options` **{Object}**: If supplied, this object is used to initialize the `base.options` object. |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
// initialize with `config` and `options` |
|||
var app = new Base({isApp: true}, {abc: true}); |
|||
app.set('foo', 'bar'); |
|||
|
|||
// values defined with the given `config` object will be on the root of the instance |
|||
console.log(app.baz); //=> undefined |
|||
console.log(app.foo); //=> 'bar' |
|||
// or use `.get` |
|||
console.log(app.get('isApp')); //=> true |
|||
console.log(app.get('foo')); //=> 'bar' |
|||
|
|||
// values defined with the given `options` object will be on `app.options |
|||
console.log(app.options.abc); //=> true |
|||
``` |
|||
|
|||
### [.is](index.js#L107) |
|||
|
|||
Set the given `name` on `app._name` and `app.is*` properties. Used for doing lookups in plugins. |
|||
|
|||
**Params** |
|||
|
|||
* `name` **{String}** |
|||
* `returns` **{Boolean}** |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
app.is('foo'); |
|||
console.log(app._name); |
|||
//=> 'foo' |
|||
console.log(app.isFoo); |
|||
//=> true |
|||
app.is('bar'); |
|||
console.log(app.isFoo); |
|||
//=> true |
|||
console.log(app.isBar); |
|||
//=> true |
|||
console.log(app._name); |
|||
//=> 'bar' |
|||
``` |
|||
|
|||
### [.isRegistered](index.js#L145) |
|||
|
|||
Returns true if a plugin has already been registered on an instance. |
|||
|
|||
Plugin implementors are encouraged to use this first thing in a plugin |
|||
to prevent the plugin from being called more than once on the same |
|||
instance. |
|||
|
|||
**Params** |
|||
|
|||
* `name` **{String}**: The plugin name. |
|||
* `register` **{Boolean}**: If the plugin if not already registered, to record it as being registered pass `true` as the second argument. |
|||
* `returns` **{Boolean}**: Returns true if a plugin is already registered. |
|||
|
|||
**Events** |
|||
|
|||
* `emits`: `plugin` Emits the name of the plugin being registered. Useful for unit tests, to ensure plugins are only registered once. |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
var base = new Base(); |
|||
base.use(function(app) { |
|||
if (app.isRegistered('myPlugin')) return; |
|||
// do stuff to `app` |
|||
}); |
|||
|
|||
// to also record the plugin as being registered |
|||
base.use(function(app) { |
|||
if (app.isRegistered('myPlugin', true)) return; |
|||
// do stuff to `app` |
|||
}); |
|||
``` |
|||
|
|||
### [.use](index.js#L175) |
|||
|
|||
Define a plugin function to be called immediately upon init. Plugins are chainable and expose the following arguments to the plugin function: |
|||
|
|||
* `app`: the current instance of `Base` |
|||
* `base`: the [first ancestor instance](#base) of `Base` |
|||
|
|||
**Params** |
|||
|
|||
* `fn` **{Function}**: plugin function to call |
|||
* `returns` **{Object}**: Returns the item instance for chaining. |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
var app = new Base() |
|||
.use(foo) |
|||
.use(bar) |
|||
.use(baz) |
|||
``` |
|||
|
|||
### [.define](index.js#L197) |
|||
|
|||
The `.define` method is used for adding non-enumerable property on the instance. Dot-notation is **not supported** with `define`. |
|||
|
|||
**Params** |
|||
|
|||
* `key` **{String}**: The name of the property to define. |
|||
* `value` **{any}** |
|||
* `returns` **{Object}**: Returns the instance for chaining. |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
// arbitrary `render` function using lodash `template` |
|||
app.define('render', function(str, locals) { |
|||
return _.template(str)(locals); |
|||
}); |
|||
``` |
|||
|
|||
### [.mixin](index.js#L222) |
|||
|
|||
Mix property `key` onto the Base prototype. If base is inherited using `Base.extend` this method will be overridden by a new `mixin` method that will only add properties to the prototype of the inheriting application. |
|||
|
|||
**Params** |
|||
|
|||
* `key` **{String}** |
|||
* `val` **{Object|Array}** |
|||
* `returns` **{Object}**: Returns the `base` instance for chaining. |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
app.mixin('foo', function() { |
|||
// do stuff |
|||
}); |
|||
``` |
|||
|
|||
### [.base](index.js#L268) |
|||
|
|||
Getter/setter used when creating nested instances of `Base`, for storing a reference to the first ancestor instance. This works by setting an instance of `Base` on the `parent` property of a "child" instance. The `base` property defaults to the current instance if no `parent` property is defined. |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
// create an instance of `Base`, this is our first ("base") instance |
|||
var first = new Base(); |
|||
first.foo = 'bar'; // arbitrary property, to make it easier to see what's happening later |
|||
|
|||
// create another instance |
|||
var second = new Base(); |
|||
// create a reference to the first instance (`first`) |
|||
second.parent = first; |
|||
|
|||
// create another instance |
|||
var third = new Base(); |
|||
// create a reference to the previous instance (`second`) |
|||
// repeat this pattern every time a "child" instance is created |
|||
third.parent = second; |
|||
|
|||
// we can always access the first instance using the `base` property |
|||
console.log(first.base.foo); |
|||
//=> 'bar' |
|||
console.log(second.base.foo); |
|||
//=> 'bar' |
|||
console.log(third.base.foo); |
|||
//=> 'bar' |
|||
// and now you know how to get to third base ;) |
|||
``` |
|||
|
|||
### [#use](index.js#L293) |
|||
|
|||
Static method for adding global plugin functions that will be added to an instance when created. |
|||
|
|||
**Params** |
|||
|
|||
* `fn` **{Function}**: Plugin function to use on each instance. |
|||
* `returns` **{Object}**: Returns the `Base` constructor for chaining |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
Base.use(function(app) { |
|||
app.foo = 'bar'; |
|||
}); |
|||
var app = new Base(); |
|||
console.log(app.foo); |
|||
//=> 'bar' |
|||
``` |
|||
|
|||
### [#extend](index.js#L337) |
|||
|
|||
Static method for inheriting the prototype and static methods of the `Base` class. This method greatly simplifies the process of creating inheritance-based applications. See [static-extend](https://github.com/jonschlinkert/static-extend) for more details. |
|||
|
|||
**Params** |
|||
|
|||
* `Ctor` **{Function}**: constructor to extend |
|||
* `methods` **{Object}**: Optional prototype properties to mix in. |
|||
* `returns` **{Object}**: Returns the `Base` constructor for chaining |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
var extend = cu.extend(Parent); |
|||
Parent.extend(Child); |
|||
|
|||
// optional methods |
|||
Parent.extend(Child, { |
|||
foo: function() {}, |
|||
bar: function() {} |
|||
}); |
|||
``` |
|||
|
|||
### [#mixin](index.js#L379) |
|||
|
|||
Used for adding methods to the `Base` prototype, and/or to the prototype of child instances. When a mixin function returns a function, the returned function is pushed onto the `.mixins` array, making it available to be used on inheriting classes whenever `Base.mixins()` is called (e.g. `Base.mixins(Child)`). |
|||
|
|||
**Params** |
|||
|
|||
* `fn` **{Function}**: Function to call |
|||
* `returns` **{Object}**: Returns the `Base` constructor for chaining |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
Base.mixin(function(proto) { |
|||
proto.foo = function(msg) { |
|||
return 'foo ' + msg; |
|||
}; |
|||
}); |
|||
``` |
|||
|
|||
### [#mixins](index.js#L401) |
|||
|
|||
Static method for running global mixin functions against a child constructor. Mixins must be registered before calling this method. |
|||
|
|||
**Params** |
|||
|
|||
* `Child` **{Function}**: Constructor function of a child class |
|||
* `returns` **{Object}**: Returns the `Base` constructor for chaining |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
Base.extend(Child); |
|||
Base.mixins(Child); |
|||
``` |
|||
|
|||
### [#inherit](index.js#L420) |
|||
|
|||
Similar to `util.inherit`, but copies all static properties, prototype properties, and getters/setters from `Provider` to `Receiver`. See [class-utils](https://github.com/jonschlinkert/class-utils#inherit) for more details. |
|||
|
|||
**Params** |
|||
|
|||
* `Receiver` **{Function}**: Receiving (child) constructor |
|||
* `Provider` **{Function}**: Providing (parent) constructor |
|||
* `returns` **{Object}**: Returns the `Base` constructor for chaining |
|||
|
|||
**Example** |
|||
|
|||
```js |
|||
Base.inherit(Foo, Bar); |
|||
``` |
|||
|
|||
## In the wild |
|||
|
|||
The following node.js applications were built with `Base`: |
|||
|
|||
* [assemble](https://github.com/assemble/assemble) |
|||
* [verb](https://github.com/verbose/verb) |
|||
* [generate](https://github.com/generate/generate) |
|||
* [scaffold](https://github.com/jonschlinkert/scaffold) |
|||
* [boilerplate](https://github.com/jonschlinkert/boilerplate) |
|||
|
|||
## Test coverage |
|||
|
|||
``` |
|||
Statements : 98.91% ( 91/92 ) |
|||
Branches : 92.86% ( 26/28 ) |
|||
Functions : 100% ( 17/17 ) |
|||
Lines : 98.9% ( 90/91 ) |
|||
``` |
|||
|
|||
## History |
|||
|
|||
### v0.11.2 |
|||
|
|||
* fixes https://github.com/micromatch/micromatch/issues/99 |
|||
|
|||
### v0.11.0 |
|||
|
|||
**Breaking changes** |
|||
|
|||
* Static `.use` and `.run` methods are now non-enumerable |
|||
|
|||
### v0.9.0 |
|||
|
|||
**Breaking changes** |
|||
|
|||
* `.is` no longer takes a function, a string must be passed |
|||
* all remaining `.debug` code has been removed |
|||
* `app._namespace` was removed (related to `debug`) |
|||
* `.plugin`, `.use`, and `.define` no longer emit events |
|||
* `.assertPlugin` was removed |
|||
* `.lazy` was removed |
|||
|
|||
## About |
|||
|
|||
### Related projects |
|||
|
|||
* [base-cwd](https://www.npmjs.com/package/base-cwd): Base plugin that adds a getter/setter for the current working directory. | [homepage](https://github.com/node-base/base-cwd "Base plugin that adds a getter/setter for the current working directory.") |
|||
* [base-data](https://www.npmjs.com/package/base-data): adds a `data` method to base-methods. | [homepage](https://github.com/node-base/base-data "adds a `data` method to base-methods.") |
|||
* [base-fs](https://www.npmjs.com/package/base-fs): base-methods plugin that adds vinyl-fs methods to your 'base' application for working with the file… [more](https://github.com/node-base/base-fs) | [homepage](https://github.com/node-base/base-fs "base-methods plugin that adds vinyl-fs methods to your 'base' application for working with the file system, like src, dest, copy and symlink.") |
|||
* [base-generators](https://www.npmjs.com/package/base-generators): Adds project-generator support to your `base` application. | [homepage](https://github.com/node-base/base-generators "Adds project-generator support to your `base` application.") |
|||
* [base-option](https://www.npmjs.com/package/base-option): Adds a few options methods to base, like `option`, `enable` and `disable`. See the readme… [more](https://github.com/node-base/base-option) | [homepage](https://github.com/node-base/base-option "Adds a few options methods to base, like `option`, `enable` and `disable`. See the readme for the full API.") |
|||
* [base-pipeline](https://www.npmjs.com/package/base-pipeline): base-methods plugin that adds pipeline and plugin methods for dynamically composing streaming plugin pipelines. | [homepage](https://github.com/node-base/base-pipeline "base-methods plugin that adds pipeline and plugin methods for dynamically composing streaming plugin pipelines.") |
|||
* [base-pkg](https://www.npmjs.com/package/base-pkg): Plugin for adding a `pkg` method that exposes pkg-store to your base application. | [homepage](https://github.com/node-base/base-pkg "Plugin for adding a `pkg` method that exposes pkg-store to your base application.") |
|||
* [base-plugins](https://www.npmjs.com/package/base-plugins): Adds 'smart plugin' support to your base application. | [homepage](https://github.com/node-base/base-plugins "Adds 'smart plugin' support to your base application.") |
|||
* [base-questions](https://www.npmjs.com/package/base-questions): Plugin for base-methods that adds methods for prompting the user and storing the answers on… [more](https://github.com/node-base/base-questions) | [homepage](https://github.com/node-base/base-questions "Plugin for base-methods that adds methods for prompting the user and storing the answers on a project-by-project basis.") |
|||
* [base-store](https://www.npmjs.com/package/base-store): Plugin for getting and persisting config values with your base-methods application. Adds a 'store' object… [more](https://github.com/node-base/base-store) | [homepage](https://github.com/node-base/base-store "Plugin for getting and persisting config values with your base-methods application. Adds a 'store' object that exposes all of the methods from the data-store library. Also now supports sub-stores!") |
|||
* [base-task](https://www.npmjs.com/package/base-task): base plugin that provides a very thin wrapper around [https://github.com/doowb/composer](https://github.com/doowb/composer) for adding task methods to… [more](https://github.com/node-base/base-task) | [homepage](https://github.com/node-base/base-task "base plugin that provides a very thin wrapper around <https://github.com/doowb/composer> for adding task methods to your application.") |
|||
|
|||
### Contributing |
|||
|
|||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). |
|||
|
|||
### Contributors |
|||
|
|||
| **Commits** | **Contributor** | |
|||
| --- | --- | |
|||
| 141 | [jonschlinkert](https://github.com/jonschlinkert) | |
|||
| 30 | [doowb](https://github.com/doowb) | |
|||
| 3 | [charlike](https://github.com/charlike) | |
|||
| 1 | [criticalmash](https://github.com/criticalmash) | |
|||
| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) | |
|||
|
|||
### Building docs |
|||
|
|||
_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ |
|||
|
|||
To generate the readme, run the following command: |
|||
|
|||
```sh |
|||
$ npm install -g verbose/verb#dev verb-generate-readme && verb |
|||
``` |
|||
|
|||
### Running tests |
|||
|
|||
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: |
|||
|
|||
```sh |
|||
$ npm install && npm test |
|||
``` |
|||
|
|||
### Author |
|||
|
|||
**Jon Schlinkert** |
|||
|
|||
* [github/jonschlinkert](https://github.com/jonschlinkert) |
|||
* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) |
|||
|
|||
### License |
|||
|
|||
Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). |
|||
Released under the [MIT License](LICENSE). |
|||
|
|||
*** |
|||
|
|||
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on September 07, 2017._ |
@ -0,0 +1,435 @@ |
|||
'use strict'; |
|||
|
|||
var util = require('util'); |
|||
var define = require('define-property'); |
|||
var CacheBase = require('cache-base'); |
|||
var Emitter = require('component-emitter'); |
|||
var isObject = require('isobject'); |
|||
var merge = require('mixin-deep'); |
|||
var pascal = require('pascalcase'); |
|||
var cu = require('class-utils'); |
|||
|
|||
/** |
|||
* Optionally define a custom `cache` namespace to use. |
|||
*/ |
|||
|
|||
function namespace(name) { |
|||
var Cache = name ? CacheBase.namespace(name) : CacheBase; |
|||
var fns = []; |
|||
|
|||
/** |
|||
* Create an instance of `Base` with the given `config` and `options`. |
|||
* |
|||
* ```js
|
|||
* // initialize with `config` and `options`
|
|||
* var app = new Base({isApp: true}, {abc: true}); |
|||
* app.set('foo', 'bar'); |
|||
* |
|||
* // values defined with the given `config` object will be on the root of the instance
|
|||
* console.log(app.baz); //=> undefined
|
|||
* console.log(app.foo); //=> 'bar'
|
|||
* // or use `.get`
|
|||
* console.log(app.get('isApp')); //=> true
|
|||
* console.log(app.get('foo')); //=> 'bar'
|
|||
* |
|||
* // values defined with the given `options` object will be on `app.options
|
|||
* console.log(app.options.abc); //=> true
|
|||
* ```
|
|||
* |
|||
* @param {Object} `config` If supplied, this object is passed to [cache-base][] to merge onto the the instance upon instantiation. |
|||
* @param {Object} `options` If supplied, this object is used to initialize the `base.options` object. |
|||
* @api public |
|||
*/ |
|||
|
|||
function Base(config, options) { |
|||
if (!(this instanceof Base)) { |
|||
return new Base(config, options); |
|||
} |
|||
Cache.call(this, config); |
|||
this.is('base'); |
|||
this.initBase(config, options); |
|||
} |
|||
|
|||
/** |
|||
* Inherit cache-base |
|||
*/ |
|||
|
|||
util.inherits(Base, Cache); |
|||
|
|||
/** |
|||
* Add static emitter methods |
|||
*/ |
|||
|
|||
Emitter(Base); |
|||
|
|||
/** |
|||
* Initialize `Base` defaults with the given `config` object |
|||
*/ |
|||
|
|||
Base.prototype.initBase = function(config, options) { |
|||
this.options = merge({}, this.options, options); |
|||
this.cache = this.cache || {}; |
|||
this.define('registered', {}); |
|||
if (name) this[name] = {}; |
|||
|
|||
// make `app._callbacks` non-enumerable
|
|||
this.define('_callbacks', this._callbacks); |
|||
if (isObject(config)) { |
|||
this.visit('set', config); |
|||
} |
|||
Base.run(this, 'use', fns); |
|||
}; |
|||
|
|||
/** |
|||
* Set the given `name` on `app._name` and `app.is*` properties. Used for doing |
|||
* lookups in plugins. |
|||
* |
|||
* ```js
|
|||
* app.is('foo'); |
|||
* console.log(app._name); |
|||
* //=> 'foo'
|
|||
* console.log(app.isFoo); |
|||
* //=> true
|
|||
* app.is('bar'); |
|||
* console.log(app.isFoo); |
|||
* //=> true
|
|||
* console.log(app.isBar); |
|||
* //=> true
|
|||
* console.log(app._name); |
|||
* //=> 'bar'
|
|||
* ```
|
|||
* @name .is |
|||
* @param {String} `name` |
|||
* @return {Boolean} |
|||
* @api public |
|||
*/ |
|||
|
|||
Base.prototype.is = function(name) { |
|||
if (typeof name !== 'string') { |
|||
throw new TypeError('expected name to be a string'); |
|||
} |
|||
this.define('is' + pascal(name), true); |
|||
this.define('_name', name); |
|||
this.define('_appname', name); |
|||
return this; |
|||
}; |
|||
|
|||
/** |
|||
* Returns true if a plugin has already been registered on an instance. |
|||
* |
|||
* Plugin implementors are encouraged to use this first thing in a plugin |
|||
* to prevent the plugin from being called more than once on the same |
|||
* instance. |
|||
* |
|||
* ```js
|
|||
* var base = new Base(); |
|||
* base.use(function(app) { |
|||
* if (app.isRegistered('myPlugin')) return; |
|||
* // do stuff to `app`
|
|||
* }); |
|||
* |
|||
* // to also record the plugin as being registered
|
|||
* base.use(function(app) { |
|||
* if (app.isRegistered('myPlugin', true)) return; |
|||
* // do stuff to `app`
|
|||
* }); |
|||
* ```
|
|||
* @name .isRegistered |
|||
* @emits `plugin` Emits the name of the plugin being registered. Useful for unit tests, to ensure plugins are only registered once. |
|||
* @param {String} `name` The plugin name. |
|||
* @param {Boolean} `register` If the plugin if not already registered, to record it as being registered pass `true` as the second argument. |
|||
* @return {Boolean} Returns true if a plugin is already registered. |
|||
* @api public |
|||
*/ |
|||
|
|||
Base.prototype.isRegistered = function(name, register) { |
|||
if (this.registered.hasOwnProperty(name)) { |
|||
return true; |
|||
} |
|||
if (register !== false) { |
|||
this.registered[name] = true; |
|||
this.emit('plugin', name); |
|||
} |
|||
return false; |
|||
}; |
|||
|
|||
/** |
|||
* Define a plugin function to be called immediately upon init. Plugins are chainable |
|||
* and expose the following arguments to the plugin function: |
|||
* |
|||
* - `app`: the current instance of `Base` |
|||
* - `base`: the [first ancestor instance](#base) of `Base` |
|||
* |
|||
* ```js
|
|||
* var app = new Base() |
|||
* .use(foo) |
|||
* .use(bar) |
|||
* .use(baz) |
|||
* ```
|
|||
* @name .use |
|||
* @param {Function} `fn` plugin function to call |
|||
* @return {Object} Returns the item instance for chaining. |
|||
* @api public |
|||
*/ |
|||
|
|||
Base.prototype.use = function(fn) { |
|||
fn.call(this, this); |
|||
return this; |
|||
}; |
|||
|
|||
/** |
|||
* The `.define` method is used for adding non-enumerable property on the instance. |
|||
* Dot-notation is **not supported** with `define`. |
|||
* |
|||
* ```js
|
|||
* // arbitrary `render` function using lodash `template`
|
|||
* app.define('render', function(str, locals) { |
|||
* return _.template(str)(locals); |
|||
* }); |
|||
* ```
|
|||
* @name .define |
|||
* @param {String} `key` The name of the property to define. |
|||
* @param {any} `value` |
|||
* @return {Object} Returns the instance for chaining. |
|||
* @api public |
|||
*/ |
|||
|
|||
Base.prototype.define = function(key, val) { |
|||
if (isObject(key)) { |
|||
return this.visit('define', key); |
|||
} |
|||
define(this, key, val); |
|||
return this; |
|||
}; |
|||
|
|||
/** |
|||
* Mix property `key` onto the Base prototype. If base is inherited using |
|||
* `Base.extend` this method will be overridden by a new `mixin` method that will |
|||
* only add properties to the prototype of the inheriting application. |
|||
* |
|||
* ```js
|
|||
* app.mixin('foo', function() { |
|||
* // do stuff
|
|||
* }); |
|||
* ```
|
|||
* @name .mixin |
|||
* @param {String} `key` |
|||
* @param {Object|Array} `val` |
|||
* @return {Object} Returns the `base` instance for chaining. |
|||
* @api public |
|||
*/ |
|||
|
|||
Base.prototype.mixin = function(key, val) { |
|||
Base.prototype[key] = val; |
|||
return this; |
|||
}; |
|||
|
|||
/** |
|||
* Non-enumberable mixin array, used by the static [Base.mixin]() method. |
|||
*/ |
|||
|
|||
Base.prototype.mixins = Base.prototype.mixins || []; |
|||
|
|||
/** |
|||
* Getter/setter used when creating nested instances of `Base`, for storing a reference |
|||
* to the first ancestor instance. This works by setting an instance of `Base` on the `parent` |
|||
* property of a "child" instance. The `base` property defaults to the current instance if |
|||
* no `parent` property is defined. |
|||
* |
|||
* ```js
|
|||
* // create an instance of `Base`, this is our first ("base") instance
|
|||
* var first = new Base(); |
|||
* first.foo = 'bar'; // arbitrary property, to make it easier to see what's happening later
|
|||
* |
|||
* // create another instance
|
|||
* var second = new Base(); |
|||
* // create a reference to the first instance (`first`)
|
|||
* second.parent = first; |
|||
* |
|||
* // create another instance
|
|||
* var third = new Base(); |
|||
* // create a reference to the previous instance (`second`)
|
|||
* // repeat this pattern every time a "child" instance is created
|
|||
* third.parent = second; |
|||
* |
|||
* // we can always access the first instance using the `base` property
|
|||
* console.log(first.base.foo); |
|||
* //=> 'bar'
|
|||
* console.log(second.base.foo); |
|||
* //=> 'bar'
|
|||
* console.log(third.base.foo); |
|||
* //=> 'bar'
|
|||
* // and now you know how to get to third base ;)
|
|||
* ```
|
|||
* @name .base |
|||
* @api public |
|||
*/ |
|||
|
|||
Object.defineProperty(Base.prototype, 'base', { |
|||
configurable: true, |
|||
get: function() { |
|||
return this.parent ? this.parent.base : this; |
|||
} |
|||
}); |
|||
|
|||
/** |
|||
* Static method for adding global plugin functions that will |
|||
* be added to an instance when created. |
|||
* |
|||
* ```js
|
|||
* Base.use(function(app) { |
|||
* app.foo = 'bar'; |
|||
* }); |
|||
* var app = new Base(); |
|||
* console.log(app.foo); |
|||
* //=> 'bar'
|
|||
* ```
|
|||
* @name #use |
|||
* @param {Function} `fn` Plugin function to use on each instance. |
|||
* @return {Object} Returns the `Base` constructor for chaining |
|||
* @api public |
|||
*/ |
|||
|
|||
define(Base, 'use', function(fn) { |
|||
fns.push(fn); |
|||
return Base; |
|||
}); |
|||
|
|||
/** |
|||
* Run an array of functions by passing each function |
|||
* to a method on the given object specified by the given property. |
|||
* |
|||
* @param {Object} `obj` Object containing method to use. |
|||
* @param {String} `prop` Name of the method on the object to use. |
|||
* @param {Array} `arr` Array of functions to pass to the method. |
|||
*/ |
|||
|
|||
define(Base, 'run', function(obj, prop, arr) { |
|||
var len = arr.length, i = 0; |
|||
while (len--) { |
|||
obj[prop](arr[i++]); |
|||
} |
|||
return Base; |
|||
}); |
|||
|
|||
/** |
|||
* Static method for inheriting the prototype and static methods of the `Base` class. |
|||
* This method greatly simplifies the process of creating inheritance-based applications. |
|||
* See [static-extend][] for more details. |
|||
* |
|||
* ```js
|
|||
* var extend = cu.extend(Parent); |
|||
* Parent.extend(Child); |
|||
* |
|||
* // optional methods
|
|||
* Parent.extend(Child, { |
|||
* foo: function() {}, |
|||
* bar: function() {} |
|||
* }); |
|||
* ```
|
|||
* @name #extend |
|||
* @param {Function} `Ctor` constructor to extend |
|||
* @param {Object} `methods` Optional prototype properties to mix in. |
|||
* @return {Object} Returns the `Base` constructor for chaining |
|||
* @api public |
|||
*/ |
|||
|
|||
define(Base, 'extend', cu.extend(Base, function(Ctor, Parent) { |
|||
Ctor.prototype.mixins = Ctor.prototype.mixins || []; |
|||
|
|||
define(Ctor, 'mixin', function(fn) { |
|||
var mixin = fn(Ctor.prototype, Ctor); |
|||
if (typeof mixin === 'function') { |
|||
Ctor.prototype.mixins.push(mixin); |
|||
} |
|||
return Ctor; |
|||
}); |
|||
|
|||
define(Ctor, 'mixins', function(Child) { |
|||
Base.run(Child, 'mixin', Ctor.prototype.mixins); |
|||
return Ctor; |
|||
}); |
|||
|
|||
Ctor.prototype.mixin = function(key, value) { |
|||
Ctor.prototype[key] = value; |
|||
return this; |
|||
}; |
|||
return Base; |
|||
})); |
|||
|
|||
/** |
|||
* Used for adding methods to the `Base` prototype, and/or to the prototype of child instances. |
|||
* When a mixin function returns a function, the returned function is pushed onto the `.mixins` |
|||
* array, making it available to be used on inheriting classes whenever `Base.mixins()` is |
|||
* called (e.g. `Base.mixins(Child)`). |
|||
* |
|||
* ```js
|
|||
* Base.mixin(function(proto) { |
|||
* proto.foo = function(msg) { |
|||
* return 'foo ' + msg; |
|||
* }; |
|||
* }); |
|||
* ```
|
|||
* @name #mixin |
|||
* @param {Function} `fn` Function to call |
|||
* @return {Object} Returns the `Base` constructor for chaining |
|||
* @api public |
|||
*/ |
|||
|
|||
define(Base, 'mixin', function(fn) { |
|||
var mixin = fn(Base.prototype, Base); |
|||
if (typeof mixin === 'function') { |
|||
Base.prototype.mixins.push(mixin); |
|||
} |
|||
return Base; |
|||
}); |
|||
|
|||
/** |
|||
* Static method for running global mixin functions against a child constructor. |
|||
* Mixins must be registered before calling this method. |
|||
* |
|||
* ```js
|
|||
* Base.extend(Child); |
|||
* Base.mixins(Child); |
|||
* ```
|
|||
* @name #mixins |
|||
* @param {Function} `Child` Constructor function of a child class |
|||
* @return {Object} Returns the `Base` constructor for chaining |
|||
* @api public |
|||
*/ |
|||
|
|||
define(Base, 'mixins', function(Child) { |
|||
Base.run(Child, 'mixin', Base.prototype.mixins); |
|||
return Base; |
|||
}); |
|||
|
|||
/** |
|||
* Similar to `util.inherit`, but copies all static properties, prototype properties, and |
|||
* getters/setters from `Provider` to `Receiver`. See [class-utils][]{#inherit} for more details. |
|||
* |
|||
* ```js
|
|||
* Base.inherit(Foo, Bar); |
|||
* ```
|
|||
* @name #inherit |
|||
* @param {Function} `Receiver` Receiving (child) constructor |
|||
* @param {Function} `Provider` Providing (parent) constructor |
|||
* @return {Object} Returns the `Base` constructor for chaining |
|||
* @api public |
|||
*/ |
|||
|
|||
define(Base, 'inherit', cu.inherit); |
|||
define(Base, 'bubble', cu.bubble); |
|||
return Base; |
|||
} |
|||
|
|||
/** |
|||
* Expose `Base` with default settings |
|||
*/ |
|||
|
|||
module.exports = namespace(); |
|||
|
|||
/** |
|||
* Allow users to define a namespace |
|||
*/ |
|||
|
|||
module.exports.namespace = namespace; |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2015, 2017, Jon Schlinkert |
|||
|
|||
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,95 @@ |
|||
# define-property [![NPM version](https://img.shields.io/npm/v/define-property.svg?style=flat)](https://www.npmjs.com/package/define-property) [![NPM monthly downloads](https://img.shields.io/npm/dm/define-property.svg?style=flat)](https://npmjs.org/package/define-property) [![NPM total downloads](https://img.shields.io/npm/dt/define-property.svg?style=flat)](https://npmjs.org/package/define-property) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/define-property.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/define-property) |
|||
|
|||
> Define a non-enumerable property on an object. |
|||
|
|||
## Install |
|||
|
|||
Install with [npm](https://www.npmjs.com/): |
|||
|
|||
```sh |
|||
$ npm install --save define-property |
|||
``` |
|||
|
|||
Install with [yarn](https://yarnpkg.com): |
|||
|
|||
```sh |
|||
$ yarn add define-property |
|||
``` |
|||
|
|||
## Usage |
|||
|
|||
**Params** |
|||
|
|||
* `obj`: The object on which to define the property. |
|||
* `prop`: The name of the property to be defined or modified. |
|||
* `descriptor`: The descriptor for the property being defined or modified. |
|||
|
|||
```js |
|||
var define = require('define-property'); |
|||
var obj = {}; |
|||
define(obj, 'foo', function(val) { |
|||
return val.toUpperCase(); |
|||
}); |
|||
|
|||
console.log(obj); |
|||
//=> {} |
|||
|
|||
console.log(obj.foo('bar')); |
|||
//=> 'BAR' |
|||
``` |
|||
|
|||
**get/set** |
|||
|
|||
```js |
|||
define(obj, 'foo', { |
|||
get: function() {}, |
|||
set: function() {} |
|||
}); |
|||
``` |
|||
|
|||
## About |
|||
|
|||
### Related projects |
|||
|
|||
* [assign-deep](https://www.npmjs.com/package/assign-deep): Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target… [more](https://github.com/jonschlinkert/assign-deep) | [homepage](https://github.com/jonschlinkert/assign-deep "Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target (first) object.") |
|||
* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow "Extend an object with the properties of additional objects. node.js/javascript util.") |
|||
* [merge-deep](https://www.npmjs.com/package/merge-deep): Recursively merge values in a javascript object. | [homepage](https://github.com/jonschlinkert/merge-deep "Recursively merge values in a javascript object.") |
|||
* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep "Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone.") |
|||
|
|||
### Contributing |
|||
|
|||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). |
|||
|
|||
### Building docs |
|||
|
|||
_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ |
|||
|
|||
To generate the readme, run the following command: |
|||
|
|||
```sh |
|||
$ npm install -g verbose/verb#dev verb-generate-readme && verb |
|||
``` |
|||
|
|||
### Running tests |
|||
|
|||
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: |
|||
|
|||
```sh |
|||
$ npm install && npm test |
|||
``` |
|||
|
|||
### Author |
|||
|
|||
**Jon Schlinkert** |
|||
|
|||
* [github/jonschlinkert](https://github.com/jonschlinkert) |
|||
* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) |
|||
|
|||
### License |
|||
|
|||
Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). |
|||
Released under the [MIT License](LICENSE). |
|||
|
|||
*** |
|||
|
|||
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.5.0, on April 20, 2017._ |
@ -0,0 +1,31 @@ |
|||
/*! |
|||
* define-property <https://github.com/jonschlinkert/define-property>
|
|||
* |
|||
* Copyright (c) 2015, 2017, Jon Schlinkert. |
|||
* Released under the MIT License. |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
var isDescriptor = require('is-descriptor'); |
|||
|
|||
module.exports = function defineProperty(obj, prop, val) { |
|||
if (typeof obj !== 'object' && typeof obj !== 'function') { |
|||
throw new TypeError('expected an object or function.'); |
|||
} |
|||
|
|||
if (typeof prop !== 'string') { |
|||
throw new TypeError('expected `prop` to be a string.'); |
|||
} |
|||
|
|||
if (isDescriptor(val) && ('set' in val || 'get' in val)) { |
|||
return Object.defineProperty(obj, prop, val); |
|||
} |
|||
|
|||
return Object.defineProperty(obj, prop, { |
|||
configurable: true, |
|||
enumerable: false, |
|||
writable: true, |
|||
value: val |
|||
}); |
|||
}; |
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue