diff --git a/css/contacts.css b/css/contacts.css
index 653a33ef..c5aca42a 100644
--- a/css/contacts.css
+++ b/css/contacts.css
@@ -31,10 +31,10 @@
}
#content textarea { font-family: inherit; }
-#content input:-moz-placeholder { color: #aaa; }
-#content input::-webkit-input-placeholder { color: #aaa; }
-#content input:-ms-input-placeholder { color: #aaa; }
-#content input:placeholder { color: #aaa; }
+#content input:-moz-placeholder #content ::-moz-placeholder, #content input[placeholder], #content input:placeholder, #content input:-ms-input-placeholder, #content input::-webkit-input-placeholder, #content input:-moz-placeholder {
+ color: #aaa;
+ text-overflow: ellipsis;
+}
#content input:not([type="checkbox"]), #content select:not(.button), #content textarea {
background-color: #fefefe; border: 1px solid #fff !important;
@@ -62,7 +62,7 @@
/* Left content */
-#leftcontent { top: 3.5em !important; padding: 0; margin: 0; }
+#leftcontent { position: absolute; top: 4em; padding: 0; margin: 0; }
#leftcontent a { display: inline-block; padding: 0; margin: 0; }
#leftcontent h3 {
cursor: pointer;
@@ -95,7 +95,16 @@
margin: auto 0 auto .3em;
}
-#groupactions { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; height: 4em; border-bottom: 1px solid #DDDDDD; }
+#groupsheader {
+ -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;
+ position: fixed;
+ padding: 0; margin:0;
+ top:3.5em; left: 12.5em;
+ height: 4em; width: 20em;
+ border-bottom: 1px solid #DDDDDD;
+ border-right: 1px solid #DDDDDD;
+ background: none repeat scroll 0 0 #F8F8F8;
+}
/*#groupactions > button, .addcontact, .import-upload-button, .doImport {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
@@ -162,8 +171,9 @@ dl.form { display: block; width: auto; margin: 0; padding: 0; cursor: normal; }
.no-svg .mail { background-image:url('%webroot%/core/img/actions/mail.png'); }
.no-svg .import, .no-svg .upload { background-image:url('%webroot%/core/img/actions/upload.png'); }
.no-svg .export, .no-svg .download { background-image:url('%webroot%/core/img/actions/download.png'); }
-.no-svg .cloud:not { background-image:url('%webroot%/core/img/places/picture.png'); }
-.no-svg .globe:not { background-image:url('%webroot%/core/img/actions/public.png'); }
+.no-svg .cloud { background-image:url('%webroot%/core/img/places/picture.png'); }
+.no-svg .globe { background-image:url('%webroot%/core/img/actions/public.png'); }
+.no-svg .settings { background-image:url('%webroot%/core/img/actions/settings.svg'); }
.no-svg .starred { background-image:url('%appswebroot%/contacts/img/starred.png'); background-size: contain; }
.no-svg .checked { background-image:url('%appswebroot%/contacts/img/checkmark-green.png'); }
.no-svg .checked.disabled { background-image:url('%appswebroot%/contacts/img/checkmark-gray.png'); cursor: default; }
@@ -186,6 +196,7 @@ dl.form { display: block; width: auto; margin: 0; padding: 0; cursor: normal; }
.svg .export,.svg .download { background-image:url('%webroot%/core/img/actions/download.svg'); }
.svg .cloud { background-image:url('%webroot%/core/img/places/picture.svg'); }
.svg .globe { background-image:url('%webroot%/core/img/actions/public.svg'); }
+.svg .settings { background-image:url('%webroot%/core/img/actions/settings.svg'); }
.svg .starred { background-image:url('%appswebroot%/contacts/img/starred.svg'); background-size: contain; }
.svg .checked { background-image:url('%appswebroot%/contacts/img/checkmark-green.svg'); }
.svg .checked.disabled { background-image:url('%appswebroot%/contacts/img/checkmark-gray.svg'); cursor: default; }
@@ -307,10 +318,18 @@ ul.propertylist { width: 450px; }
.addressbooks-settings td.active, .addressbooks-settings td.action { width: 20px; }
#contacts-settings .settings {
- width: 20px; height: 20px;
- float: left;
+ /*width: 20px; height: 20px;
+ float: left;*/
+ color: transparent;
+ background-repeat: no-repeat;
+ background-position: left center;
+ background-origin: content-box;
background-image:url('%webroot%/core/img/actions/settings.svg');
}
+#contacts-settings .settings:hover {
+ font-weight: normal;
+ color: #666666;
+}
#contacts-settings.open {
height: auto;
}
@@ -331,7 +350,7 @@ ul.propertylist { width: 450px; }
z-index: 2;
}
#contacts-settings li,#contacts-settings li:hover { background-color: transparent; white-space: nowrap; }
-#contacts-settings a.action { width: 20px; height: 20px; }
+#contacts-settings a.action:not(.settings) { width: 16px; height: 16px; }
#contacts-settings .actions { float: right; }
.multiselectoptions label { display: block; }
@@ -433,7 +452,7 @@ input[type="checkbox"].propertytype { width: 10px; }
/* Right content layout */
-#rightcontent, .rightcontent { position:fixed; top: 7.5em; left: 32.5em; overflow-x:hidden; overflow-y: auto; }
+#rightcontent, .rightcontent { position:absolute; top: 4em; left: 20em; overflow-x:hidden; overflow-y: auto; }
/* Contact layout */
diff --git a/css/placeholder_polyfill.css b/css/placeholder_polyfill.css
new file mode 100644
index 00000000..a0464add
--- /dev/null
+++ b/css/placeholder_polyfill.css
@@ -0,0 +1,32 @@
+span.placeholder{
+ position:absolute;
+ font-size:75%;
+ color:#999;
+ font-family:sans-serif;
+ padding:4px 3px;
+ z-index:1;
+ cursor:text;
+}
+
+span.placeholder-hide-except-screenreader {
+ clip: rect(1px 1px 1px 1px);
+ clip: rect(1px, 1px, 1px, 1px);
+ padding:0 !important;
+ border:0 !important;
+ height: 1px !important;
+ width: 1px !important;
+ overflow: hidden;
+}
+
+span.placeholder-hide{
+ display:none;
+}
+
+/* overwrite for the HTML5 Boilerplate way to hide labels */
+label.visuallyhidden-with-placeholder{
+ /*clip: auto !important;*/
+ height:auto !important;
+ overflow: visible !important;
+ position:absolute !important;
+ left:-999em;
+}
\ No newline at end of file
diff --git a/css/placeholder_polyfill.min.css b/css/placeholder_polyfill.min.css
new file mode 100644
index 00000000..5a967b0b
--- /dev/null
+++ b/css/placeholder_polyfill.min.css
@@ -0,0 +1,8 @@
+/**
+ * Html5 Placeholder Polyfill - v2.0.3 - 2012-08-21
+ * web: * http://blog.ginader.de/dev/jquery/HTML5-placeholder-polyfill/
+ * issues: * https://github.com/ginader/HTML5-placeholder-polyfill/issues
+ * Copyright (c) 2012 Dirk Ginader; Licensed MIT, GPL
+*/
+label span.placeholder{position:absolute;font-size:75%;color:#999;font-family:sans-serif;padding:4px 3px;z-index:1;cursor:text}label span.placeholder-hide-except-screenreader{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);padding:0!important;border:0!important;height:1px!important;width:1px!important;overflow:hidden}
+label span.placeholder-hide{display:none}label.visuallyhidden-with-placeholder{height:auto!important;overflow:visible!important;position:absolute!important;left:-999em}
\ No newline at end of file
diff --git a/index.php b/index.php
index aef4bacd..75bc804a 100644
--- a/index.php
+++ b/index.php
@@ -49,16 +49,13 @@ $maxUploadFilesize = min($maxUploadFilesize, $freeSpace);
OCP\Util::addscript('contacts', 'multiselect');
OCP\Util::addscript('', 'oc-vcategories');
+OCP\Util::addscript('contacts', 'modernizr.custom');
OCP\Util::addscript('contacts', 'app');
OCP\Util::addscript('contacts', 'contacts');
-OCP\Util::addscript('contacts', 'modernizr');
-OCP\Util::addscript('contacts', 'placeholder.polyfill.jquery');
OCP\Util::addscript('contacts', 'expanding');
OCP\Util::addscript('contacts', 'jquery.combobox');
OCP\Util::addscript('files', 'jquery.fileupload');
-//OCP\Util::addscript('core', 'jquery.inview');
OCP\Util::addscript('contacts', 'jquery.Jcrop');
-OCP\Util::addscript('contacts', 'jquery.multi-autocomplete');
OCP\Util::addStyle('contacts', 'multiselect');
OCP\Util::addStyle('contacts', 'jquery.combobox');
OCP\Util::addStyle('contacts', 'jquery.Jcrop');
diff --git a/js/app.js b/js/app.js
index c9f589da..b786821c 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1,3 +1,11 @@
+Modernizr.load({
+ test: Modernizr.input.placeholder,
+ nope: [
+ OC.filePath('contacts', 'css', 'placeholder_polyfill.min.css'),
+ OC.filePath('contacts', 'js', 'placeholder_polyfill.jquery.min.combo.js')
+ ]
+});
+
var utils = {};
/**
@@ -22,11 +30,11 @@ utils.isArray = function(obj) {
utils.isInt = function(s) {
return typeof s === 'number' && (s.toString().search(/^-?[0-9]+$/) === 0);
-}
+};
utils.isUInt = function(s) {
return typeof s === 'number' && (s.toString().search(/^[0-9]+$/) === 0);
-}
+};
/**
* utils.type
@@ -50,7 +58,7 @@ utils.moveCursorToEnd = function(el) {
range.collapse(false);
range.select();
}
-}
+};
if (typeof Object.create !== 'function') {
Object.create = function (o) {
@@ -77,8 +85,9 @@ Array.prototype.clean = function(deleteValue) {
// Keep it DRY ;)
var wrongKey = function(event) {
- return (event.type === 'keydown' && (event.keyCode !== 32 && event.keyCode !== 13));
-}
+ return ((event.type === 'keydown' || event.type === 'keypress')
+ && (event.keyCode !== 32 && event.keyCode !== 13));
+};
/**
* Simply notifier
@@ -140,7 +149,7 @@ OC.notify = function(params) {
self.notifier.removeData(dataid);
});
}
-}
+};
var GroupList = function(groupList, listItemTmpl) {
this.$groupList = groupList;
@@ -158,7 +167,7 @@ var GroupList = function(groupList, listItemTmpl) {
if(response.status !== 'success') {
OC.notify({message:response.data.message});
}
- })
+ });
} else {
self.selectGroup({element:$(this)});
}
@@ -166,19 +175,19 @@ var GroupList = function(groupList, listItemTmpl) {
this.$groupListItemTemplate = listItemTmpl;
this.categories = [];
-}
+};
GroupList.prototype.nameById = function(id) {
- return this.findById(id).contents().filter(function(){ return(this.nodeType == 3); }).text().trim()
-}
+ return this.findById(id).contents().filter(function(){ return(this.nodeType == 3); }).text().trim();
+};
GroupList.prototype.findById = function(id) {
return this.$groupList.find('h3[data-id="' + id + '"]');
-}
+};
GroupList.prototype.isFavorite = function(contactid) {
return this.inGroup(contactid, 'fav');
-}
+};
GroupList.prototype.selectGroup = function(params) {
var id, $elem;
@@ -203,15 +212,15 @@ GroupList.prototype.selectGroup = function(params) {
$(document).trigger('status.group.selected', {
id: this.lastgroup,
type: $elem.data('type'),
- contacts: $elem.data('contacts'),
+ contacts: $elem.data('contacts')
});
-}
+};
GroupList.prototype.inGroup = function(contactid, groupid) {
var $groupelem = this.findById(groupid);
var contacts = $groupelem.data('contacts');
return (contacts.indexOf(contactid) !== -1);
-}
+};
GroupList.prototype.setAsFavorite = function(contactid, state, cb) {
contactid = parseInt(contactid);
@@ -251,7 +260,7 @@ GroupList.prototype.setAsFavorite = function(contactid, state, cb) {
}
});
}
-}
+};
/**
* Add one or more contact ids to a group
@@ -315,7 +324,7 @@ GroupList.prototype.addTo = function(contactid, groupid, cb) {
$(document).trigger('status.group.contactadded', {
contactid: contactid,
groupid: groupid,
- groupname: self.nameById(groupid),
+ groupname: self.nameById(groupid)
});
}
} else {
@@ -325,14 +334,14 @@ GroupList.prototype.addTo = function(contactid, groupid, cb) {
}
});
}
-}
+};
GroupList.prototype.removeFrom = function(contactid, groupid, cb) {
console.log('GroupList.removeFrom', contactid, groupid);
var $groupelem = this.findById(groupid);
var contacts = $groupelem.data('contacts');
var ids = [];
-
+
// If it's the 'all' group simply decrement the number
if(groupid === 'all') {
var $numelem = $groupelem.find('.numcontacts');
@@ -405,7 +414,7 @@ GroupList.prototype.removeFrom = function(contactid, groupid, cb) {
}
});
}
-}
+};
GroupList.prototype.removeFromAll = function(contactid, alsospecial) {
var self = this;
@@ -413,11 +422,11 @@ GroupList.prototype.removeFromAll = function(contactid, alsospecial) {
$.each(this.$groupList.find(selector), function(i, group) {
self.removeFrom(contactid, $(this).data('id'));
});
-}
+};
GroupList.prototype.categoriesChanged = function(newcategories) {
console.log('GroupList.categoriesChanged, I should do something');
-}
+};
GroupList.prototype.contactDropped = function(event, ui) {
var dragitem = ui.draggable, droptarget = $(this);
@@ -430,7 +439,7 @@ GroupList.prototype.contactDropped = function(event, ui) {
$(this).data('obj').addTo(dragitem.data('id'), $(this).data('id'));
}
}
-}
+};
GroupList.prototype.deleteGroup = function(groupid, cb) {
var $elem = this.findById(groupid);
@@ -445,7 +454,7 @@ GroupList.prototype.deleteGroup = function(groupid, cb) {
groupid: groupid,
newgroupid: parseInt($newelem.data('id')),
groupname: self.nameById(groupid),
- contacts: contacts,
+ contacts: contacts
});
$elem.remove();
self.selectGroup({element:$newelem});
@@ -456,7 +465,7 @@ GroupList.prototype.deleteGroup = function(groupid, cb) {
cb(jsondata);
}
});
-}
+};
GroupList.prototype.editGroup = function(id) {
var self = this;
@@ -476,16 +485,16 @@ GroupList.prototype.editGroup = function(id) {
self.addGroup({name:name, element:$elem}, function(response) {
if(response.status === 'success') {
$elem.prepend(name).removeClass('editing').attr('data-id', response.id);
- $input.next('.checked').remove()
- $input.remove()
+ $input.next('.checked').remove();
+ $input.remove();
self.$editelem = null;
} else {
$input.prop('disabled', false);
OC.notify({message:response.message});
}
});
- }
-
+ };
+
if(typeof id === 'undefined') {
// Add new group
var tmpl = this.$groupListItemTemplate;
@@ -493,7 +502,7 @@ GroupList.prototype.editGroup = function(id) {
id: 'new',
type: 'category',
num: 0,
- name: '',
+ name: ''
});
var $input = $('');
self.$editelem.prepend($input).addClass('editing');
@@ -533,11 +542,11 @@ GroupList.prototype.editGroup = function(id) {
var $input = $(''
+ + 'title="' + t('contacts', 'Shared by {owner}', {owner:shared.userid}) + '" />';
var $elem = (tmpl).octemplate({
id: shared.id,
type: 'shared',
num: '', //jsondata.data.shared.length,
- name: shared.displayname,
+ name: shared.displayname
});
$elem.find('.numcontacts').after(sharedindicator);
$elem.data('obj', self);
@@ -685,27 +694,27 @@ GroupList.prototype.loadGroups = function(numcontacts, cb) {
console.log('stop sorting', $(this));
var ids = [];
$.each($(this).children('h3[data-type="category"]'), function(i, elem) {
- ids.push($(elem).data('id'))
- })
+ ids.push($(elem).data('id'));
+ });
self.sortorder = ids;
$(document).trigger('status.groups.sorted', {
- sortorder: self.sortorder.join(','),
+ sortorder: self.sortorder.join(',')
});
- },
+ }
});
var $elem = self.findById(self.lastgroup);
$elem.addClass('active');
$(document).trigger('status.group.selected', {
id: self.lastgroup,
type: $elem.data('type'),
- contacts: $elem.data('contacts'),
+ contacts: $elem.data('contacts')
});
} // TODO: else
if(typeof cb === 'function') {
cb();
}
});
-}
+};
OC.Contacts = OC.Contacts || {
init:function(id) {
@@ -713,7 +722,7 @@ OC.Contacts = OC.Contacts || {
$(document).ajaxError(function(e, xhr, settings, exception) {
// Don't try to get translation because it's likely a network error.
OC.notify({
- message: 'error in: ' + settings.url + ', '+'error: ' + xhr.responseText,
+ message: 'error in: ' + settings.url + ', '+'error: ' + xhr.responseText
});
});
}
@@ -777,9 +786,10 @@ OC.Contacts = OC.Contacts || {
// The weird double loading is because jquery apparently doesn't
// create a searchable object from a script element.
$.each($($('#contactDetailsTemplate').html()), function(idx, node) {
- if(node.nodeType === Node.ELEMENT_NODE && node.nodeName === 'DIV') {
+ var $node = $(node);
+ if($node.is('div')) {
var $tmpl = $(node.innerHTML);
- self.detailTemplates[$tmpl.data('element')] = $(node);
+ self.detailTemplates[$tmpl.data('element')] = $node;
}
});
this.$groupListItemTemplate = $('#groupListItemTemplate');
@@ -853,7 +863,7 @@ OC.Contacts = OC.Contacts || {
var id = parseInt(data.id);
console.log('contact', data.id, 'deleted');
// update counts on group lists
- self.groups.removeFromAll(data.id, true)
+ self.groups.removeFromAll(data.id, true);
});
$(document).bind('status.contact.added', function(e, data) {
@@ -867,7 +877,7 @@ OC.Contacts = OC.Contacts || {
});
$(document).bind('status.contact.enabled', function(e, enabled) {
- console.log('status.contact.enabled', enabled)
+ console.log('status.contact.enabled', enabled);
/*if(enabled) {
self.showActions(['back', 'download', 'delete', 'groups']);
} else {
@@ -906,7 +916,7 @@ OC.Contacts = OC.Contacts || {
self.dontScroll = false;
}, 100);
}
- self.currentlistid = result.id
+ self.currentlistid = result.id;
});
$(document).bind('status.nomorecontacts', function(e, result) {
@@ -931,7 +941,7 @@ OC.Contacts = OC.Contacts || {
console.log('waiting for contacts to load');
setTimeout(function() {
$(document).trigger('request.loadcontact', {
- id: result.id,
+ id: result.id
});
}, 1000);
}
@@ -1008,7 +1018,7 @@ OC.Contacts = OC.Contacts || {
$.each(result.contacts, function(idx, contactid) {
var contact = self.contacts.findById(contactid);
console.log('contactid', contactid, contact);
-
+
self.contacts.findById(contactid).removeFromGroup(result.groupname);
});
});
@@ -1083,7 +1093,7 @@ OC.Contacts = OC.Contacts || {
if(self.$settings.find($(e.target)).length == 0) {
self.$settings.switchClass('open', '');
}
- }
+ };
if(self.$settings.hasClass('open')) {
self.$settings.switchClass('open', '');
$('body').unbind('click', bodyListener);
@@ -1096,7 +1106,7 @@ OC.Contacts = OC.Contacts || {
self.uploadPhoto(this.files);
});
- $('#groupactions > .addgroup').on('click keydown',function(event) {
+ $('#groupsheader > .addgroup').on('click keydown',function(event) {
if(wrongKey(event)) {
return;
}
@@ -1145,8 +1155,8 @@ OC.Contacts = OC.Contacts || {
// If a contact is open the action is only applied to that,
// otherwise on all selected items.
if(self.currentid) {
- ids = [self.currentid,];
- buildnow = true
+ ids = [self.currentid];
+ buildnow = true;
} else {
ids = self.contacts.getSelectedContacts();
}
@@ -1156,7 +1166,7 @@ OC.Contacts = OC.Contacts || {
if(!self.currentid) {
self.showActions(['add']);
}
-
+
if($opt.val() === 'add') { // Add new group
action = 'add';
console.log('add group...');
@@ -1179,7 +1189,7 @@ OC.Contacts = OC.Contacts || {
$(document).trigger('status.contact.addedtogroup', {
contactid: id,
groupid: groupId,
- groupname: groupName,
+ groupname: groupName
});
}, 1000);
});
@@ -1194,7 +1204,7 @@ OC.Contacts = OC.Contacts || {
});
return;
}
-
+
groupName = $opt.text(), groupId = $opt.val();
console.log('trut', groupName, groupId);
@@ -1215,7 +1225,7 @@ OC.Contacts = OC.Contacts || {
$(document).trigger('status.contact.addedtogroup', {
contactid: id,
groupid: groupId,
- groupname: groupName,
+ groupname: groupName
});
}, 1000);
});
@@ -1241,7 +1251,7 @@ OC.Contacts = OC.Contacts || {
$(document).trigger('status.contact.removedfromgroup', {
contactid: id,
groupid: groupId,
- groupname: groupName,
+ groupname: groupName
});
});
} else {
@@ -1281,7 +1291,7 @@ OC.Contacts = OC.Contacts || {
}
self.openContact($(this).data('id'));
});
-
+
this.$settings.find('h3').on('click keydown', function(event) {
if(wrongKey(event)) {
return;
@@ -1294,7 +1304,7 @@ OC.Contacts = OC.Contacts || {
var $list = $(this).next('ul');
if($(this).data('id') === 'addressbooks') {
console.log('addressbooks');
-
+
if(!self.$addressbookTmpl) {
self.$addressbookTmpl = $('#addressbookTemplate');
}
@@ -1302,9 +1312,9 @@ OC.Contacts = OC.Contacts || {
$list.empty();
$.each(self.contacts.addressbooks, function(id, book) {
var $li = self.$addressbookTmpl.octemplate({
- id: id,
+ id: id,
permissions: book.permissions,
- displayname: book.displayname,
+ displayname: book.displayname
});
$list.append($li);
@@ -1317,7 +1327,7 @@ OC.Contacts = OC.Contacts || {
var $li = $(this).parents('li').first();
$.ajax({
type:'POST',
- url:OC.filePath('contacts', 'ajax', 'addressbook/delete.php'),
+ url:OC.filePath('contacts', 'ajax', 'addressbook/delete.php'),
data:{ id: id },
success:function(jsondata) {
console.log(jsondata);
@@ -1343,7 +1353,7 @@ OC.Contacts = OC.Contacts || {
error:function(jqXHR, textStatus, errorThrown) {
OC.notify({message:textStatus + ': ' + errorThrown});
id = false;
- },
+ }
});
});
$list.find('a.action.globe').on('click keypress', function() {
@@ -1376,13 +1386,13 @@ OC.Contacts = OC.Contacts || {
$.ajax({
type:'POST',
async:false,
- url:OC.filePath('contacts', 'ajax', 'addressbook/add.php'),
+ url:OC.filePath('contacts', 'ajax', 'addressbook/add.php'),
data:{ name: name },
success:function(jsondata) {
console.log(jsondata);
if(jsondata.status == 'success') {
self.contacts.setAddressbook(jsondata.data.addressbook);
- id = jsondata.data.addressbook.id
+ id = jsondata.data.addressbook.id;
} else {
OC.notify({message:jsondata.data.message});
}
@@ -1390,10 +1400,10 @@ OC.Contacts = OC.Contacts || {
error:function(jqXHR, textStatus, errorThrown) {
OC.notify({message:textStatus + ': ' + errorThrown});
id = false;
- },
+ }
});
return id;
- }
+ };
self.$importIntoSelect.empty();
$.each(self.contacts.addressbooks, function(id, book) {
@@ -1403,7 +1413,7 @@ OC.Contacts = OC.Contacts || {
createCallback:addAddressbookCallback,
singleSelect: true,
createText:String(t('contacts', 'Add address book')),
- minWidth: 120,
+ minWidth: 120
});
}
@@ -1420,11 +1430,11 @@ OC.Contacts = OC.Contacts || {
$(this).hide();
self.currentid = 'new';
// Properties that the contact doesn't know
- console.log('addContact, groupid', self.currentgroup)
+ console.log('addContact, groupid', self.currentgroup);
var groupprops = {
favorite: false,
groups: self.groups.categories,
- currentgroup: {id:self.currentgroup, name:self.groups.nameById(self.currentgroup)},
+ currentgroup: {id:self.currentgroup, name:self.groups.nameById(self.currentgroup)}
};
self.tmpcontact = self.contacts.addContact(groupprops);
self.$rightContent.prepend(self.tmpcontact);
@@ -1450,7 +1460,7 @@ OC.Contacts = OC.Contacts || {
return;
}
console.log('download');
- document.location.href = OC.linkTo('contacts', 'export.php')
+ document.location.href = OC.linkTo('contacts', 'export.php')
+ '?selectedids=' + self.contacts.getSelectedContacts().join(',');
});
@@ -1558,14 +1568,14 @@ OC.Contacts = OC.Contacts || {
$status.text(t('contacts', 'Importing from {filename}...', {filename:fileName})).fadeIn();
doImport(fileName, aid, function(response) {
if(response.status === 'success') {
- $status.text(t('contacts', '{success} imported, {failed} failed.',
+ $status.text(t('contacts', '{success} imported, {failed} failed.',
{success:response.data.imported, failed:response.data.failed})).fadeIn();
}
delete uploadingFiles[fileName];
numfiles -= 1; uploadedfiles -= 1;
$progressbar.progressbar('value',50+(50/(todo-uploadedfiles)));
});
- })
+ });
//$status.text(t('contacts', 'Importing...')).fadeIn();
waitForImport();
};
@@ -1605,7 +1615,7 @@ OC.Contacts = OC.Contacts || {
$.each(files, function(i, file) {
var fileName = file.name;
console.log('file.name', file.name);
- var jqXHR = $('#import_fileupload').fileupload('send',
+ var jqXHR = $('#import_fileupload').fileupload('send',
{
files: file,
formData: function(form) {
@@ -1624,7 +1634,7 @@ OC.Contacts = OC.Contacts || {
})
.error(function(jqXHR, textStatus, errorThrown) {
console.log(textStatus);
- OC.notify({message:errorThrown + ': ' + textStatus,});
+ OC.notify({message:errorThrown + ': ' + textStatus});
});
uploadingFiles[fileName] = jqXHR;
});
@@ -1673,9 +1683,9 @@ OC.Contacts = OC.Contacts || {
$('#upload input.stop').hide();
}
}
- })
+ });
});
-
+
$(document).on('keypress', function(event) {
if(!$(event.target).is('body')) {
return;
@@ -1731,7 +1741,7 @@ OC.Contacts = OC.Contacts || {
break;
case 34: // PageDown
case 78: // n
- console.log('page down')
+ console.log('page down');
break;
case 79: // o
console.log('open contact?');
@@ -1757,7 +1767,7 @@ OC.Contacts = OC.Contacts || {
});
- // find all with a title attribute and tipsy them
+ // find all with a title attribute and tipsy them
$('.tooltipped.downwards:not(.onfocus)').tipsy({gravity: 'n'});
$('.tooltipped.upwards:not(.onfocus)').tipsy({gravity: 's'});
$('.tooltipped.rightwards:not(.onfocus)').tipsy({gravity: 'w'});
@@ -1792,8 +1802,8 @@ OC.Contacts = OC.Contacts || {
});
$(this).dialog('close');
},
- 'Cancel':function() {
- $(this).dialog('close');
+ 'Cancel':function() {
+ $(this).dialog('close');
return false;
}
},
@@ -1803,12 +1813,12 @@ OC.Contacts = OC.Contacts || {
},
open: function(event, ui) {
$dlg.find('input').focus();
- },
+ }
});
},
setAllChecked: function(checked) {
var selector = checked ? 'input:checkbox:visible:not(checked)' : 'input:checkbox:visible:checked';
- $.each(self.$contactList.find(selector), function() {
+ $.each(this.$contactList.find(selector), function() {
$(this).prop('checked', checked);
});
},
@@ -1847,7 +1857,7 @@ OC.Contacts = OC.Contacts || {
var groupprops = {
favorite: this.groups.isFavorite(this.currentid),
groups: this.groups.categories,
- currentgroup: {id:this.currentgroup, name:this.groups.nameById(this.currentgroup)},
+ currentgroup: {id:this.currentgroup, name:this.groups.nameById(this.currentgroup)}
};
var $contactelem = this.contacts.showContact(this.currentid, groupprops);
var self = this;
@@ -1879,7 +1889,7 @@ OC.Contacts = OC.Contacts || {
OC.notify({
message:t(
'contacts',
- 'The file you are trying to upload exceed the maximum size for file uploads on this server.'),
+ 'The file you are trying to upload exceed the maximum size for file uploads on this server.')
});
return;
} else {
@@ -1898,12 +1908,12 @@ OC.Contacts = OC.Contacts || {
},
cloudPhotoSelected:function(id, path) {
var self = this;
- console.log('cloudPhotoSelected, id', id)
+ console.log('cloudPhotoSelected, id', id);
$.getJSON(OC.filePath('contacts', 'ajax', 'oc_photo.php'),
{path: path, id: id},function(jsondata) {
if(jsondata.status == 'success') {
//alert(jsondata.data.page);
- self.editPhoto(jsondata.data.id, jsondata.data.tmp)
+ self.editPhoto(jsondata.data.id, jsondata.data.tmp);
$('#edit_photo_dialog_img').html(jsondata.data.page);
}
else{
@@ -1917,7 +1927,7 @@ OC.Contacts = OC.Contacts || {
{id: id}, function(jsondata) {
if(jsondata.status == 'success') {
//alert(jsondata.data.page);
- self.editPhoto(jsondata.data.id, jsondata.data.tmp)
+ self.editPhoto(jsondata.data.id, jsondata.data.tmp);
$('#edit_photo_dialog_img').html(jsondata.data.page);
}
else{
@@ -1926,7 +1936,7 @@ OC.Contacts = OC.Contacts || {
});
},
editPhoto:function(id, tmpkey) {
- console.log('editPhoto', id, tmpkey)
+ console.log('editPhoto', id, tmpkey);
$('.tipsy').remove();
// Simple event handler, called from onChange and onSelect
// event handlers, as per the Jcrop invocation above
@@ -1961,7 +1971,7 @@ OC.Contacts = OC.Contacts || {
maxSize: [399, 399],
bgColor: 'black',
bgOpacity: .4,
- boxWidth: 400,
+ boxWidth: 400,
boxHeight: 400,
setSelect: [ 100, 130, 50, 50 ]//,
//aspectRatio: 0.8
@@ -2000,7 +2010,7 @@ OC.Contacts = OC.Contacts || {
if(jsondata && jsondata.status === 'success') {
// load cropped photo.
$(document).trigger('status.contact.photoupdated', {
- id: jsondata.data.id,
+ id: jsondata.data.id
});
} else {
if(!jsondata) {
@@ -2016,14 +2026,14 @@ OC.Contacts = OC.Contacts || {
$.ajax({
type:'POST',
async:false,
- url:OC.filePath('contacts', 'ajax', 'addressbook/add.php'),
+ url:OC.filePath('contacts', 'ajax', 'addressbook/add.php'),
data:{ name: data.name, description: data.description },
success:function(jsondata) {
if(jsondata.status == 'success') {
if(typeof cb === 'function') {
cb({
status:'success',
- addressbook: jsondata.data.addressbook,
+ addressbook: jsondata.data.addressbook
});
}
} else {
@@ -2040,7 +2050,7 @@ OC.Contacts = OC.Contacts || {
$('body').append('
');
var $dlg = $('#addressbook_dialog').html(data).octemplate({
nameplaceholder: t('contacts', 'Enter name'),
- descplaceholder: t('contacts', 'Enter description'),
+ descplaceholder: t('contacts', 'Enter description')
}).dialog({
modal: true, height: 'auto', width: 'auto',
title: t('contacts', 'Select addressbook'),
@@ -2062,7 +2072,7 @@ OC.Contacts = OC.Contacts || {
if(data.status === 'success') {
cb({
status:'success',
- addressbook:data.addressbook,
+ addressbook:data.addressbook
});
} else {
cb({status:'error'});
@@ -2075,7 +2085,7 @@ OC.Contacts = OC.Contacts || {
if(typeof cb === 'function') {
cb({
status:'success',
- addressbook:self.contacts.addressbooks[parseInt(aid)],
+ addressbook:self.contacts.addressbooks[parseInt(aid)]
});
}
$(this).dialog('close');
@@ -2100,7 +2110,7 @@ OC.Contacts = OC.Contacts || {
|| book.permissions & OC.PERMISSION_DELETE)) {
var row = ''
+ ' | | '
- + '{description} |
'
+ + '{description} | ';
var $row = $(row).octemplate({
id:book.id,
displayname:book.displayname,
@@ -2113,12 +2123,12 @@ OC.Contacts = OC.Contacts || {
$lastrow.find('input.name,input.desc').on('focus', function(e) {
$lastrow.find('input[type="radio"]').prop('checked', true);
});
- },
+ }
});
}).error(function() {
OC.notify({message: t('contacts', 'Network or server error. Please inform administrator.')});
});
- },
+ }
};
(function( $ ) {
diff --git a/js/contacts.js b/js/contacts.js
index 92006244..b143282c 100644
--- a/js/contacts.js
+++ b/js/contacts.js
@@ -23,15 +23,16 @@ OC.Contacts = OC.Contacts || {};
this.$fullTemplate = fulltemplate;
this.detailTemplates = detailtemplates;
+ this.undoQueue = [];
this.multi_properties = ['EMAIL', 'TEL', 'IMPP', 'ADR', 'URL'];
- }
+ };
Contact.prototype.showActions = function(act) {
this.$footer.children().hide();
if(act && act.length > 0) {
this.$footer.children('.'+act.join(',.')).show();
}
- }
+ };
Contact.prototype.setAsSaving = function(obj, state) {
if(!obj) {
@@ -44,10 +45,35 @@ OC.Contacts = OC.Contacts || {};
} else {
$(obj).removeClass('loading');
}*/
- }
+ };
+ Contact.prototype.pushToUndo = function(params) {
+ // Check if the same property has been changed before
+ // and update it's checksum if so.
+ if(typeof params.oldchecksum !== 'undefined') {
+ $.each(this.undoQueue, function(idx, item) {
+ if(item.checksum === params.oldchecksum) {
+ item.checksum = params.newchecksum;
+ if(params.action === 'delete') {
+ item.action = 'delete';
+ }
+ return false; // Break loop
+ }
+ });
+ }
+ this.undoQueue.push({
+ action:params.action,
+ name: params.name,
+ checksum: params.newchecksum,
+ newvalue: params.newvalue,
+ oldvalue: params.oldvalue
+ });
+ console.log('undoQueue', this.undoQueue);
+ }
+
Contact.prototype.addProperty = function($option, name) {
console.log('Contact.addProperty', name)
+ var $elem;
switch(name) {
case 'NICKNAME':
case 'TITLE':
@@ -82,7 +108,15 @@ OC.Contacts = OC.Contacts || {};
$elem.find('input.value').addClass('new');
break;
}
- }
+
+ if($elem) {
+ $elem.find('select.type[name="parameters[TYPE][]"]')
+ .combobox({
+ singleclick: true,
+ classes: ['propertytype', 'float', 'label'],
+ });
+ }
+ };
Contact.prototype.deleteProperty = function(params) {
var obj = params.obj;
@@ -109,7 +143,7 @@ OC.Contacts = OC.Contacts || {};
if(!jsondata) {
$(document).trigger('status.contact.error', {
status: 'error',
- message: t('contacts', 'Network or server error. Please inform administrator.'),
+ message: t('contacts', 'Network or server error. Please inform administrator.')
});
self.setAsSaving(obj, false);
return false;
@@ -119,6 +153,12 @@ OC.Contacts = OC.Contacts || {};
if(self.multi_properties.indexOf(element) !== -1) {
// First find out if an existing element by looking for checksum
var checksum = self.checksumFor(obj);
+ self.pushToUndo({
+ action:'delete',
+ name: element,
+ oldchecksum: self.checksumFor(obj),
+ newvalue: self.valueFor(obj)
+ });
if(checksum) {
for(var i in self.data[element]) {
if(self.data[element][i].checksum === checksum) {
@@ -130,22 +170,31 @@ OC.Contacts = OC.Contacts || {};
}
$container.remove();
} else {
+ self.pushToUndo({
+ action:'delete',
+ name: element,
+ newvalue: $container.find('input.value').val()
+ });
self.setAsSaving(obj, false);
self.$fullelem.find('[data-element="' + element.toLowerCase() + '"]').hide();
$container.find('input.value').val('');
self.$addMenu.find('option[value="' + element.toUpperCase() + '"]').prop('disabled', false);
}
+ $(document).trigger('status.contact.updated', {
+ property: element,
+ contact: self
+ });
return true;
} else {
$(document).trigger('status.contact.error', {
status: 'error',
- message: jsondata.data.message,
+ message: jsondata.data.message
});
self.setAsSaving(obj, false);
return false;
}
},'json');
- }
+ };
/**
* @brief Act on change of a property.
@@ -192,7 +241,7 @@ OC.Contacts = OC.Contacts || {};
if(!jsondata) {
$(document).trigger('status.contact.error', {
status: 'error',
- message: t('contacts', 'Network or server error. Please inform administrator.'),
+ message: t('contacts', 'Network or server error. Please inform administrator.')
});
$(obj).addClass('error');
self.setAsSaving(obj, false);
@@ -205,24 +254,40 @@ OC.Contacts = OC.Contacts || {};
if(self.multi_properties.indexOf(element) !== -1) {
// First find out if an existing element by looking for checksum
var checksum = self.checksumFor(obj);
- if(checksum) {
- for(var i in self.data[element]) {
- if(self.data[element][i].checksum === checksum) {
+ var value = self.valueFor(obj);
+ var parameters = self.parametersFor(obj);
+ if(checksum && checksum !== 'new') {
+ self.pushToUndo({
+ action:'save',
+ name: element,
+ newchecksum: jsondata.data.checksum,
+ oldchecksum: checksum,
+ newvalue: value,
+ oldvalue: obj.defaultValue
+ });
+ $.each(self.data[element], function(i, el) {
+ if(el.checksum === checksum) {
self.data[element][i] = {
name: element,
- value: self.valueFor(obj),
- parameters: self.parametersFor(obj),
- checksum: jsondata.data.checksum,
- }
- break;
+ value: value,
+ parameters: parameters,
+ checksum: jsondata.data.checksum
+ };
+ return false;
}
- }
+ });
} else {
$(obj).removeClass('new');
+ self.pushToUndo({
+ action:'add',
+ name: element,
+ newchecksum: jsondata.data.checksum,
+ newvalue: value,
+ });
self.data[element].push({
name: element,
- value: self.valueFor(obj),
- parameters: self.parametersFor(obj),
+ value: value,
+ parameters: parameters,
checksum: jsondata.data.checksum,
});
}
@@ -230,17 +295,20 @@ OC.Contacts = OC.Contacts || {};
} else {
// Save value and parameters internally
var value = obj ? self.valueFor(obj) : params.value;
+ self.pushToUndo({
+ action: ((obj && obj.defaultValue) || self.data[element].length) ? 'save' : 'add', // FIXME
+ name: element,
+ newvalue: value,
+ });
switch(element) {
case 'CATEGORIES':
// We deal with this in addToGroup()
break;
case 'FN':
if(!self.data.FN || !self.data.FN.length) {
- self.data.FN = [{name:'FN', value:'', parameters:[]}]
+ self.data.FN = [{name:'FN', value:'', parameters:[]}];
}
self.data.FN[0]['value'] = value;
- // Update the list element
- self.$listelem.find('.nametext').text(value);
var nempty = true;
if(!self.data.N) {
// TODO: Maybe add a method for constructing new elements?
@@ -272,10 +340,6 @@ OC.Contacts = OC.Contacts || {};
}
, 500);
}
- $(document).trigger('status.contact.renamed', {
- id: self.id,
- contact: self,
- });
break;
case 'N':
if(!utils.isArray(value)) {
@@ -295,7 +359,7 @@ OC.Contacts = OC.Contacts || {};
name: element,
value: value,
parameters: self.parametersFor(obj),
- checksum: jsondata.data.checksum,
+ checksum: jsondata.data.checksum
};
break;
default:
@@ -303,25 +367,29 @@ OC.Contacts = OC.Contacts || {};
}
}
self.setAsSaving(obj, false);
+ $(document).trigger('status.contact.updated', {
+ property: element,
+ contact: self
+ });
return true;
} else {
$(document).trigger('status.contact.error', {
status: 'error',
- message: jsondata.data.message,
+ message: jsondata.data.message
});
self.setAsSaving(obj, false);
return false;
}
},'json');
- }
+ };
/**
* Hide contact list element.
*/
Contact.prototype.hide = function() {
this.getListItemElement().hide();
- }
-
+ };
+
/**
* Remove any open contact from the DOM.
*/
@@ -333,7 +401,7 @@ OC.Contacts = OC.Contacts || {};
} else {
return false;
}
- }
+ };
/**
* Remove any open contact from the DOM and detach it's list
@@ -348,7 +416,7 @@ OC.Contacts = OC.Contacts || {};
this.$listelem.detach();
return this;
}
- }
+ };
/**
* Set a contacts list element as (un)checked
@@ -359,7 +427,7 @@ OC.Contacts = OC.Contacts || {};
this.$listelem.find('input:checkbox').prop('checked', checked);
return this;
}
- }
+ };
/**
* Set a contact to en/disabled depending on its permissions.
@@ -376,13 +444,13 @@ OC.Contacts = OC.Contacts || {};
$(this).prop('disabled', !enabled);
});
$(document).trigger('status.contact.enabled', enabled);
- }
+ };
/**
* Add a contact from data store and remove it from the DOM
* @params params. An object which can contain the optional properties:
- * aid: The id of the addressbook to add the contact to. Per default it will be added to the first.
- * fn: The formatted name of the contact.
+ * aid: The id of the addressbook to add the contact to. Per default it will be added to the first.
+ * fn: The formatted name of the contact.
* @param cb Optional callback function which
* @returns The callback gets an object as argument with a variable 'status' of either 'success'
* or 'error'. On success the 'data' property of that object contains the contact id as 'id', the
@@ -395,7 +463,7 @@ OC.Contacts = OC.Contacts || {};
if(!jsondata) {
$(document).trigger('status.contact.error', {
status: 'error',
- message: t('contacts', 'Network or server error. Please inform administrator.'),
+ message: t('contacts', 'Network or server error. Please inform administrator.')
});
return false;
}
@@ -404,7 +472,7 @@ OC.Contacts = OC.Contacts || {};
self.access.id = parseInt(jsondata.data.aid);
self.data = jsondata.data.details;
// Add contact to current group
- if(self.groupprops && self.groupprops.currentgroup.name !== 'all'
+ if(self.groupprops && self.groupprops.currentgroup.name !== 'all'
&& self.groupprops.currentgroup.name !== 'fav') {
if(!self.data.CATEGORIES) {
self.data.CATEGORIES = [{value:[self.groupprops.currentgroup.name], parameters:[]}];
@@ -413,25 +481,25 @@ OC.Contacts = OC.Contacts || {};
// Tell OC.Contacts to save in backend
$(document).trigger('request.contact.addtogroup', {
id: self.id,
- groupid: self.groupprops.currentgroup.id,
+ groupid: self.groupprops.currentgroup.id
});
}
}
$(document).trigger('status.contact.added', {
id: self.id,
- contact: self,
+ contact: self
});
}
if(typeof cb == 'function') {
cb(jsondata);
}
});
- }
+ };
/**
* Delete contact from data store and remove it from the DOM
* @param cb Optional callback function which
* @returns An object with a variable 'status' of either success
- * or 'error'
+ * or 'error'
*/
Contact.prototype.destroy = function(cb) {
var self = this;
@@ -460,7 +528,7 @@ OC.Contacts = OC.Contacts || {};
cb(retval);
}
});
- }
+ };
Contact.prototype.queryStringFor = function(obj) {
var q = 'id=' + this.id;
@@ -483,23 +551,23 @@ OC.Contacts = OC.Contacts || {};
}
}
return q;
- }
+ };
Contact.prototype.propertyContainerFor = function(obj) {
return $(obj).hasClass('propertycontainer')
? $(obj)
: $(obj).parents('.propertycontainer').first();
- }
+ };
Contact.prototype.checksumFor = function(obj) {
return this.propertyContainerFor(obj).data('checksum');
- }
+ };
Contact.prototype.valueFor = function(obj) {
var $container = this.propertyContainerFor(obj);
- console.assert($container.length > 0, 'Couldn\'t find container for ' + $(obj))
- return $container.is('input')
- ? $container.val()
+ console.assert($container.length > 0, 'Couldn\'t find container for ' + $(obj));
+ return $container.is('input')
+ ? $container.val()
: (function() {
var $elem = $container.find('textarea.value,input.value:not(:checkbox)');
console.assert($elem.length > 0, 'Couldn\'t find value for ' + $container.data('element'));
@@ -513,7 +581,7 @@ OC.Contacts = OC.Contacts || {};
return retval;
}
})();
- }
+ };
Contact.prototype.parametersFor = function(obj, asText) {
var parameters = [];
@@ -536,12 +604,12 @@ OC.Contacts = OC.Contacts || {};
parameters[paramname].push(val);
});
return parameters;
- }
+ };
Contact.prototype.propertyTypeFor = function(obj) {
var ptype = this.propertyContainerFor(obj).data('element');
return ptype ? ptype.toUpperCase() : null;
- }
+ };
/**
* Render the list item
@@ -555,7 +623,7 @@ OC.Contacts = OC.Contacts || {};
tel: this.getPreferredValue('TEL', ''),
adr: this.getPreferredValue('ADR', []).clean('').join(', '),
categories: this.getPreferredValue('CATEGORIES', [])
- .clean('').join(' / '),
+ .clean('').join(' / ')
});
if(this.access.owner !== OC.currentUser
&& !(this.access.permissions & OC.PERMISSION_UPDATE
@@ -563,7 +631,7 @@ OC.Contacts = OC.Contacts || {};
this.$listelem.find('input:checkbox').prop('disabled', true).css('opacity', '0');
}
return this.$listelem;
- }
+ };
/**
* Render the full contact
@@ -588,13 +656,13 @@ OC.Contacts = OC.Contacts || {};
$.datepicker.parseDate('yy-mm-dd',
this.getPreferredValue('BDAY', '').substring(0, 10)))
: '',
- note: this.getPreferredValue('NOTE', ''),
+ note: this.getPreferredValue('NOTE', '')
}
: {id:'', favorite:'', name:'', nickname:'', title:'', org:'', bday:'', note:'', n0:'', n1:'', n2:'', n3:'', n4:''};
this.$fullelem = this.$fullTemplate.octemplate(values).data('contactobject', this);
this.$footer = this.$fullelem.find('footer');
-
+
this.$fullelem.find('.tooltipped.rightwards.onfocus').tipsy({trigger: 'focus', gravity: 'w'});
this.$fullelem.on('submit', function() {
return false;
@@ -625,12 +693,12 @@ OC.Contacts = OC.Contacts || {};
$editor.toggle('blind');
$('body').unbind('click', bodyListener);
}
- }
+ };
$editor.toggle('blind', function() {
$('body').bind('click', bodyListener);
});
});
-
+
this.$fullelem.on('click keydown', '.delete', function(event) {
$('.tipsy').remove();
if(wrongKey(event)) {
@@ -646,32 +714,36 @@ OC.Contacts = OC.Contacts || {};
}
if($(this).is('.close') || $(this).is('.cancel')) {
$(document).trigger('request.contact.close', {
- id: self.id,
+ id: self.id
});
} else if($(this).is('.export')) {
$(document).trigger('request.contact.export', {
- id: self.id,
+ id: self.id
});
} else if($(this).is('.delete')) {
$(document).trigger('request.contact.delete', {
- id: self.id,
+ id: self.id
});
}
return false;
});
this.$fullelem.on('keypress', '.value,.parameter', function(event) {
if(event.keyCode === 13 && $(this).is('input')) {
- console.log('Enter');
$(this).trigger('change');
+ // Prevent a second save on blur.
+ this.defaultValue = this.value;
return false;
} else if(event.keyCode === 27) {
$(document).trigger('request.contact.close', {
- id: self.id,
+ id: self.id
});
}
});
-
+
this.$fullelem.on('change', '.value,.parameter', function(event) {
+ if(this.value === this.defaultValue) {
+ return;
+ }
self.saveProperty({obj:event.target});
});
@@ -681,7 +753,7 @@ OC.Contacts = OC.Contacts || {};
});
this.$fullelem.find('.favorite').on('click', function () {
var state = $(this).hasClass('active');
- if(!this.data) {
+ if(!self.data) {
return;
}
if(state) {
@@ -691,7 +763,7 @@ OC.Contacts = OC.Contacts || {};
}
$(document).trigger('request.contact.setasfavorite', {
id: self.id,
- state: !state,
+ state: !state
});
});
this.loadPhoto();
@@ -757,7 +829,7 @@ OC.Contacts = OC.Contacts || {};
//console.log('param', param);
if(param.toUpperCase() == 'PREF') {
var $cb = $property.find('input[type="checkbox"]');
- $cb.attr('checked', 'checked')
+ $cb.attr('checked', 'checked');
meta.push($cb.attr('title'));
}
else if(param.toUpperCase() == 'TYPE') {
@@ -798,7 +870,7 @@ OC.Contacts = OC.Contacts || {};
$property.find('select.type[name="parameters[TYPE][]"]')
.combobox({
singleclick: true,
- classes: ['propertytype', 'float', 'label'],
+ classes: ['propertytype', 'float', 'label']
});
}
$list.append($property);
@@ -810,19 +882,19 @@ OC.Contacts = OC.Contacts || {};
&& !(this.access.permissions & OC.PERMISSION_UPDATE
|| this.access.permissions & OC.PERMISSION_DELETE)) {
this.setEnabled(false);
- this.showActions(['close']);
+ this.showActions(['close', 'export']);
} else {
this.setEnabled(true);
this.showActions(['close', 'add', 'export', 'delete']);
}
return this.$fullelem;
- }
+ };
Contact.prototype.isEditable = function() {
return ((this.access.owner === OC.currentUser)
|| (this.access.permissions & OC.PERMISSION_UPDATE
|| this.access.permissions & OC.PERMISSION_DELETE));
- }
+ };
/**
* Render a simple property. Used for EMAIL and TEL.
@@ -837,7 +909,7 @@ OC.Contacts = OC.Contacts || {};
? { value: property.value, checksum: property.checksum }
: { value: '', checksum: 'new' };
return this.detailTemplates[name].octemplate(values);
- }
+ };
/**
* Render an ADR (address) property.
@@ -865,7 +937,7 @@ OC.Contacts = OC.Contacts || {};
adr4: property.value[4] || '',
adr5: property.value[5] || '',
adr6: property.value[6] || '',
- idx: idx,
+ idx: idx
}
: {value:'', checksum:'new', adr0:'', adr1:'', adr2:'', adr3:'', adr4:'', adr5:'', adr6:'', idx: idx};
var $elem = this.detailTemplates['adr'].octemplate(values);
@@ -889,7 +961,7 @@ OC.Contacts = OC.Contacts || {};
$('body').unbind('click', bodyListener);
});
}
- }
+ };
$viewer.slideUp();
$editor.toggle('blind', function() {
$('body').bind('click', bodyListener);
@@ -914,7 +986,7 @@ OC.Contacts = OC.Contacts || {};
label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
value: item.name,
country: item.countryName
- }
+ };
}));
}
});
@@ -924,7 +996,7 @@ OC.Contacts = OC.Contacts || {};
if(ui.item && $elem.find('.value.country').val().trim().length == 0) {
$elem.find('.value.country').val(ui.item.country);
}
- },
+ }
});
$elem.find('.value.country')
.autocomplete({
@@ -946,15 +1018,15 @@ OC.Contacts = OC.Contacts || {};
return {
label: item.name,
value: item.name
- }
+ };
}));
}
});
},
- minLength: 2,
+ minLength: 2
});
return $elem;
- }
+ };
/**
* Render an IMPP (Instant Messaging) property.
@@ -967,10 +1039,10 @@ OC.Contacts = OC.Contacts || {};
}
var values = property ? {
value: property.value,
- checksum: property.checksum,
+ checksum: property.checksum
} : {value: '', checksum: 'new'};
return this.detailTemplates['impp'].octemplate(values);
- }
+ };
/**
* Render the PHOTO property.
@@ -983,7 +1055,7 @@ OC.Contacts = OC.Contacts || {};
this.$photowrapper.addClass('loading').addClass('wait');
var $phototools = this.$fullelem.find('#phototools');
delete this.photo;
- $('img.contactphoto').remove()
+ $('img.contactphoto').remove();
this.photo = new Image();
$(this.photo).load(function () {
$(this).addClass('contactphoto');
@@ -1012,17 +1084,17 @@ OC.Contacts = OC.Contacts || {};
$phototools.find('.edit').on('click', function() {
$(document).trigger('request.edit.contactphoto', {
- id: self.id,
+ id: self.id
});
});
$phototools.find('.cloud').on('click', function() {
$(document).trigger('request.select.contactphoto.fromcloud', {
- id: self.id,
+ id: self.id
});
});
$phototools.find('.upload').on('click', function() {
$(document).trigger('request.select.contactphoto.fromlocal', {
- id: self.id,
+ id: self.id
});
});
if(this.data && this.data.PHOTO) {
@@ -1039,7 +1111,7 @@ OC.Contacts = OC.Contacts || {};
.css('background', 'url(' + OC.filePath('', '', 'remote.php')+'/contactthumbnail?id='+self.id+refreshstr + ')');
});
}
- }
+ };
/**
* Get the jquery element associated with this object
@@ -1049,7 +1121,7 @@ OC.Contacts = OC.Contacts || {};
this.renderListItem();
}
return this.$listelem;
- }
+ };
/**
* Get the preferred value for a property.
@@ -1079,7 +1151,7 @@ OC.Contacts = OC.Contacts || {};
});
}
return pref;
- }
+ };
/**
* Returns true/false depending on the contact being in the
@@ -1097,9 +1169,9 @@ OC.Contacts = OC.Contacts || {};
if(typeof categories[i] === 'string' && (name.toLowerCase() === categories[i].toLowerCase())) {
return true;
}
- };
+ }
return false;
- }
+ };
/**
* Add this contact to a group
@@ -1108,7 +1180,7 @@ OC.Contacts = OC.Contacts || {};
Contact.prototype.addToGroup = function(name) {
console.log('addToGroup', name);
if(!this.data.CATEGORIES) {
- this.data.CATEGORIES = [{value:[name]},];
+ this.data.CATEGORIES = [{value:[name]}];
} else {
if(this.inGroup(name)) {
return;
@@ -1120,7 +1192,7 @@ OC.Contacts = OC.Contacts || {};
}
}
this.saveProperty({name:'CATEGORIES', value:this.data.CATEGORIES[0].value.join(',') });
- }
+ };
/**
* Remove this contact to a group
@@ -1151,7 +1223,7 @@ OC.Contacts = OC.Contacts || {};
}
}
this.saveProperty({name:'CATEGORIES', value:this.data.CATEGORIES[0].value.join(',') });
- }
+ };
Contact.prototype.setCurrent = function(on) {
if(on) {
@@ -1162,9 +1234,9 @@ OC.Contacts = OC.Contacts || {};
$(document).trigger('status.contact.currentlistitem', {
id: this.id,
pos: Math.round(this.$listelem.position().top),
- height: Math.round(this.$listelem.height()),
+ height: Math.round(this.$listelem.height())
});
- }
+ };
Contact.prototype.next = function() {
var $next = this.$listelem.next('tr');
@@ -1174,10 +1246,10 @@ OC.Contacts = OC.Contacts || {};
$(document).trigger('status.contact.currentlistitem', {
id: parseInt($next.data('id')),
pos: Math.round($next.position().top),
- height: Math.round($next.height()),
+ height: Math.round($next.height())
});
}
- }
+ };
Contact.prototype.prev = function() {
var $prev = this.$listelem.prev('tr');
@@ -1187,10 +1259,10 @@ OC.Contacts = OC.Contacts || {};
$(document).trigger('status.contact.currentlistitem', {
id: parseInt($prev.data('id')),
pos: Math.round($prev.position().top),
- height: Math.round($prev.height()),
+ height: Math.round($prev.height())
});
}
- }
+ };
var ContactList = function(contactlist, contactlistitemtemplate, contactfulltemplate, contactdetailtemplates) {
//console.log('ContactList', contactlist, contactlistitemtemplate, contactfulltemplate, contactdetailtemplates);
@@ -1209,10 +1281,13 @@ OC.Contacts = OC.Contacts || {};
self.insertContact(data.contact.renderListItem());
});
- $(document).bind('status.contact.renamed', function(e, data) {
- self.insertContact(data.contact.getListItemElement().detach());
+ $(document).bind('status.contact.updated', function(e, data) {
+ if(['FN', 'EMAIL', 'TEL', 'ADR', 'CATEGORIES'].indexOf(data.property) !== -1) {
+ data.contact.getListItemElement().remove();
+ self.insertContact(self.contacts[parseInt(data.contact.id)].renderListItem());
+ }
});
- }
+ };
/**
* Show/hide contacts belonging to an addressbook.
@@ -1230,7 +1305,7 @@ OC.Contacts = OC.Contacts || {};
this.contacts[contact].getListItemElement().hide();
}
}
- }
+ };
/**
* Show/hide contacts belonging to shared addressbooks.
@@ -1247,7 +1322,7 @@ OC.Contacts = OC.Contacts || {};
}
}
}
- }
+ };
/**
* Show contacts in list
@@ -1272,7 +1347,7 @@ OC.Contacts = OC.Contacts || {};
this.contacts[contact].getListItemElement().show();
}
}
- }
+ };
ContactList.prototype.contactPos = function(id) {
if(!id) {
@@ -1282,15 +1357,15 @@ OC.Contacts = OC.Contacts || {};
var $elem = this.contacts[parseInt(id)].getListItemElement();
var pos = $elem.offset().top - this.$contactList.offset().top + this.$contactList.scrollTop();
return pos;
- }
+ };
ContactList.prototype.hideContact = function(id) {
this.contacts[parseInt(id)].hide();
- }
+ };
ContactList.prototype.closeContact = function(id) {
this.contacts[parseInt(id)].close();
- }
+ };
/**
* Returns a Contact object by searching for its id
@@ -1312,7 +1387,7 @@ OC.Contacts = OC.Contacts || {};
} else if(utils.isArray(id)) {
$.extend(this.deletionQueue, id);
} else {
- throw { name: 'WrongParameterType', message: 'ContactList.delayedDelete only accept integers or arrays.'}
+ throw { name: 'WrongParameterType', message: 'ContactList.delayedDelete only accept integers or arrays.'};
}
$.each(this.deletionQueue, function(idx, id) {
self.contacts[id].detach().setChecked(false);
@@ -1326,7 +1401,7 @@ OC.Contacts = OC.Contacts || {};
e.returnValue = String(warn);
}
return warn;
- }
+ };
}
if(this.$contactList.find('tr:visible').length === 0) {
$(document).trigger('status.visiblecontacts');
@@ -1350,7 +1425,7 @@ OC.Contacts = OC.Contacts || {};
window.onbeforeunload = null;
}
});
- }
+ };
/**
* Delete a contact with this id
@@ -1379,7 +1454,7 @@ OC.Contacts = OC.Contacts || {};
if(response.status === 'success') {
delete self.contacts[id];
$(document).trigger('status.contact.deleted', {
- id: id,
+ id: id
});
self.length -= 1;
if(self.length === 0) {
@@ -1389,7 +1464,7 @@ OC.Contacts = OC.Contacts || {};
OC.notify({message:response.message});
}
});
- }
+ };
/**
* Opens the contact with this id in edit mode
@@ -1399,7 +1474,7 @@ OC.Contacts = OC.Contacts || {};
ContactList.prototype.showContact = function(id, props) {
console.assert(typeof id === 'number', 'ContactList.showContact called with a non-number');
this.currentContact = id;
- console.log('Contacts.showContact', id, this.contacts[this.currentContact], this.contacts)
+ console.log('Contacts.showContact', id, this.contacts[this.currentContact], this.contacts);
return this.contacts[this.currentContact].renderContact(props);
};
@@ -1413,10 +1488,10 @@ OC.Contacts = OC.Contacts || {};
revert: 'invalid',
//containment: '#content',
opacity: 0.8, helper: 'clone',
- zIndex: 1000,
+ zIndex: 1000
});
var name = $contact.find('.nametext').text().toLowerCase();
- var added = false
+ var added = false;
this.$contactList.find('tr').each(function() {
if ($(this).find('.nametext').text().toLowerCase().localeCompare(name) > 0) {
$(this).before($contact);
@@ -1429,7 +1504,7 @@ OC.Contacts = OC.Contacts || {};
}
$contact.show();
return $contact;
- }
+ };
/**
* Add contact
@@ -1450,7 +1525,7 @@ OC.Contacts = OC.Contacts || {};
this.contacts[this.currentContact].close();
}
return contact.renderContact(props);
- }
+ };
/**
* Get contacts selected in list
@@ -1464,17 +1539,17 @@ OC.Contacts = OC.Contacts || {};
contacts.push(parseInt($(b).parents('tr').first().data('id')));
});
return contacts;
- }
+ };
ContactList.prototype.setCurrent = function(id, deselect_other) {
- self = this;
+ var self = this;
if(deselect_other === true) {
$.each(this.contacts, function(contact) {
self.contacts[contact].setCurrent(false);
});
}
this.contacts[parseInt(id)].setCurrent(true);
- }
+ };
// Should only be neccesary with progressive loading, but it's damn fast, so... ;)
ContactList.prototype.doSort = function() {
@@ -1485,10 +1560,18 @@ OC.Contacts = OC.Contacts || {};
return $(a).find('td.name').text().toUpperCase().localeCompare($(b).find('td.name').text().toUpperCase());
});
+ var items = [];
$.each(rows, function(index, row) {
- self.$contactList.append(row);
+ items.push(row);
+ if(items.length === 100) {
+ self.$contactList.append(items);
+ items = [];
+ }
});
- }
+ if(items.length > 0) {
+ self.$contactList.append(items);
+ }
+ };
/**
* Save addressbook data
@@ -1496,8 +1579,8 @@ OC.Contacts = OC.Contacts || {};
*/
ContactList.prototype.unsetAddressbook = function(id) {
delete this.addressbooks[id];
- }
-
+ };
+
/**
* Save addressbook data
* @param object book
@@ -1510,9 +1593,9 @@ OC.Contacts = OC.Contacts || {};
id: parseInt(book.id),
displayname: book.displayname,
description: book.description,
- active: Boolean(parseInt(book.active)),
+ active: Boolean(parseInt(book.active))
};
- }
+ };
/**
* Load contacts
* @param int offset
@@ -1527,6 +1610,7 @@ OC.Contacts = OC.Contacts || {};
$.each(jsondata.data.addressbooks, function(i, book) {
self.setAddressbook(book);
});
+ var items = [];
$.each(jsondata.data.contacts, function(c, contact) {
self.contacts[parseInt(contact.id)]
= new Contact(
@@ -1540,6 +1624,7 @@ OC.Contacts = OC.Contacts || {};
);
self.length +=1;
var $item = self.contacts[parseInt(contact.id)].renderListItem();
+ items.push($item.get(0));
$item.draggable({
distance: 10,
revert: 'invalid',
@@ -1547,10 +1632,18 @@ OC.Contacts = OC.Contacts || {};
opacity: 0.8, helper: 'clone',
zIndex: 1000,
});
- self.$contactList.append($item);
- //self.insertContact(item);
+ if(items.length === 100) {
+ self.$contactList.append(items);
+ items = [];
+ }
});
- self.doSort();
+ if(items.length > 0) {
+ self.$contactList.append(items);
+ }
+ setTimeout(function() {
+ self.doSort();
+ }
+ , 2000);
$(document).trigger('status.contacts.loaded', {
status: true,
numcontacts: jsondata.data.contacts.length
diff --git a/js/loader.js b/js/loader.js
index ce869a70..f3c12caa 100644
--- a/js/loader.js
+++ b/js/loader.js
@@ -75,7 +75,7 @@ Contacts_Import={
}
});
}
-}
+};
var openContact = function(id) {
if(typeof OC.Contacts !== 'undefined') {
@@ -83,7 +83,7 @@ var openContact = function(id) {
} else {
window.location.href = OC.linkTo('contacts', 'index.php') + '?id=' + id;
}
-}
+};
$(document).ready(function(){
if(typeof FileActions !== 'undefined'){
@@ -91,5 +91,5 @@ $(document).ready(function(){
FileActions.setDefault('text/vcard','importaddressbook');
FileActions.register('text/x-vcard','importaddressbook', OC.PERMISSION_READ, '', Contacts_Import.importdialog);
FileActions.setDefault('text/x-vcard','importaddressbook');
- };
+ }
});
\ No newline at end of file
diff --git a/js/modernizr.custom.js b/js/modernizr.custom.js
new file mode 100644
index 00000000..523a0833
--- /dev/null
+++ b/js/modernizr.custom.js
@@ -0,0 +1,814 @@
+/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
+ * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-canvas-draganddrop-audio-video-input-inputtypes-localstorage-sessionstorage-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-elem_track-load
+ */
+;
+
+
+
+window.Modernizr = (function( window, document, undefined ) {
+
+ var version = '2.6.2',
+
+ Modernizr = {},
+
+ enableClasses = true,
+
+ docElement = document.documentElement,
+
+ mod = 'modernizr',
+ modElem = document.createElement(mod),
+ mStyle = modElem.style,
+
+ inputElem = document.createElement('input') ,
+
+ smile = ':)',
+
+ toString = {}.toString,
+
+ prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
+
+
+
+ omPrefixes = 'Webkit Moz O ms',
+
+ cssomPrefixes = omPrefixes.split(' '),
+
+ domPrefixes = omPrefixes.toLowerCase().split(' '),
+
+ ns = {'svg': 'http://www.w3.org/2000/svg'},
+
+ tests = {},
+ inputs = {},
+ attrs = {},
+
+ classes = [],
+
+ slice = classes.slice,
+
+ featureName,
+
+
+ injectElementWithStyles = function( rule, callback, nodes, testnames ) {
+
+ var style, ret, node, docOverflow,
+ div = document.createElement('div'),
+ body = document.body,
+ fakeBody = body || document.createElement('body');
+
+ if ( parseInt(nodes, 10) ) {
+ while ( nodes-- ) {
+ node = document.createElement('div');
+ node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
+ div.appendChild(node);
+ }
+ }
+
+ style = ['',''].join('');
+ div.id = mod;
+ (body ? div : fakeBody).innerHTML += style;
+ fakeBody.appendChild(div);
+ if ( !body ) {
+ fakeBody.style.background = '';
+ fakeBody.style.overflow = 'hidden';
+ docOverflow = docElement.style.overflow;
+ docElement.style.overflow = 'hidden';
+ docElement.appendChild(fakeBody);
+ }
+
+ ret = callback(div, rule);
+ if ( !body ) {
+ fakeBody.parentNode.removeChild(fakeBody);
+ docElement.style.overflow = docOverflow;
+ } else {
+ div.parentNode.removeChild(div);
+ }
+
+ return !!ret;
+
+ },
+
+ testMediaQuery = function( mq ) {
+
+ var matchMedia = window.matchMedia || window.msMatchMedia;
+ if ( matchMedia ) {
+ return matchMedia(mq).matches;
+ }
+
+ var bool;
+
+ injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
+ bool = (window.getComputedStyle ?
+ getComputedStyle(node, null) :
+ node.currentStyle)['position'] == 'absolute';
+ });
+
+ return bool;
+
+ },
+
+
+ isEventSupported = (function() {
+
+ var TAGNAMES = {
+ 'select': 'input', 'change': 'input',
+ 'submit': 'form', 'reset': 'form',
+ 'error': 'img', 'load': 'img', 'abort': 'img'
+ };
+
+ function isEventSupported( eventName, element ) {
+
+ element = element || document.createElement(TAGNAMES[eventName] || 'div');
+ eventName = 'on' + eventName;
+
+ var isSupported = eventName in element;
+
+ if ( !isSupported ) {
+ if ( !element.setAttribute ) {
+ element = document.createElement('div');
+ }
+ if ( element.setAttribute && element.removeAttribute ) {
+ element.setAttribute(eventName, '');
+ isSupported = is(element[eventName], 'function');
+
+ if ( !is(element[eventName], 'undefined') ) {
+ element[eventName] = undefined;
+ }
+ element.removeAttribute(eventName);
+ }
+ }
+
+ element = null;
+ return isSupported;
+ }
+ return isEventSupported;
+ })(),
+
+
+ _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
+
+ if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
+ hasOwnProp = function (object, property) {
+ return _hasOwnProperty.call(object, property);
+ };
+ }
+ else {
+ hasOwnProp = function (object, property) {
+ return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
+ };
+ }
+
+
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function bind(that) {
+
+ var target = this;
+
+ if (typeof target != "function") {
+ throw new TypeError();
+ }
+
+ var args = slice.call(arguments, 1),
+ bound = function () {
+
+ if (this instanceof bound) {
+
+ var F = function(){};
+ F.prototype = target.prototype;
+ var self = new F();
+
+ var result = target.apply(
+ self,
+ args.concat(slice.call(arguments))
+ );
+ if (Object(result) === result) {
+ return result;
+ }
+ return self;
+
+ } else {
+
+ return target.apply(
+ that,
+ args.concat(slice.call(arguments))
+ );
+
+ }
+
+ };
+
+ return bound;
+ };
+ }
+
+ function setCss( str ) {
+ mStyle.cssText = str;
+ }
+
+ function setCssAll( str1, str2 ) {
+ return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
+ }
+
+ function is( obj, type ) {
+ return typeof obj === type;
+ }
+
+ function contains( str, substr ) {
+ return !!~('' + str).indexOf(substr);
+ }
+
+ function testProps( props, prefixed ) {
+ for ( var i in props ) {
+ var prop = props[i];
+ if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
+ return prefixed == 'pfx' ? prop : true;
+ }
+ }
+ return false;
+ }
+
+ function testDOMProps( props, obj, elem ) {
+ for ( var i in props ) {
+ var item = obj[props[i]];
+ if ( item !== undefined) {
+
+ if (elem === false) return props[i];
+
+ if (is(item, 'function')){
+ return item.bind(elem || obj);
+ }
+
+ return item;
+ }
+ }
+ return false;
+ }
+
+ function testPropsAll( prop, prefixed, elem ) {
+
+ var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
+ props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
+
+ if(is(prefixed, "string") || is(prefixed, "undefined")) {
+ return testProps(props, prefixed);
+
+ } else {
+ props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
+ return testDOMProps(props, prefixed, elem);
+ }
+ } tests['flexbox'] = function() {
+ return testPropsAll('flexWrap');
+ };
+
+
+ tests['flexboxlegacy'] = function() {
+ return testPropsAll('boxDirection');
+ };
+
+
+ tests['canvas'] = function() {
+ var elem = document.createElement('canvas');
+ return !!(elem.getContext && elem.getContext('2d'));
+ }; tests['webgl'] = function() {
+ return !!window.WebGLRenderingContext;
+ };
+
+
+ tests['touch'] = function() {
+ var bool;
+
+ if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
+ bool = true;
+ } else {
+ injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {
+ bool = node.offsetTop === 9;
+ });
+ }
+
+ return bool;
+ };
+
+
+
+ tests['geolocation'] = function() {
+ return 'geolocation' in navigator;
+ };
+
+
+
+ tests['draganddrop'] = function() {
+ var div = document.createElement('div');
+ return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
+ };
+
+
+
+ tests['rgba'] = function() {
+ setCss('background-color:rgba(150,255,150,.5)');
+
+ return contains(mStyle.backgroundColor, 'rgba');
+ };
+
+ tests['hsla'] = function() {
+ setCss('background-color:hsla(120,40%,100%,.5)');
+
+ return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
+ };
+
+ tests['multiplebgs'] = function() {
+ setCss('background:url(https://),url(https://),red url(https://)');
+
+ return (/(url\s*\(.*?){3}/).test(mStyle.background);
+ }; tests['backgroundsize'] = function() {
+ return testPropsAll('backgroundSize');
+ };
+
+ tests['borderimage'] = function() {
+ return testPropsAll('borderImage');
+ };
+
+
+
+ tests['borderradius'] = function() {
+ return testPropsAll('borderRadius');
+ };
+
+ tests['boxshadow'] = function() {
+ return testPropsAll('boxShadow');
+ };
+
+ tests['textshadow'] = function() {
+ return document.createElement('div').style.textShadow === '';
+ };
+
+
+ tests['opacity'] = function() {
+ setCssAll('opacity:.55');
+
+ return (/^0.55$/).test(mStyle.opacity);
+ };
+
+
+ tests['cssanimations'] = function() {
+ return testPropsAll('animationName');
+ };
+
+
+ tests['csscolumns'] = function() {
+ return testPropsAll('columnCount');
+ };
+
+
+ tests['cssgradients'] = function() {
+ var str1 = 'background-image:',
+ str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
+ str3 = 'linear-gradient(left top,#9f9, white);';
+
+ setCss(
+ (str1 + '-webkit- '.split(' ').join(str2 + str1) +
+ prefixes.join(str3 + str1)).slice(0, -str1.length)
+ );
+
+ return contains(mStyle.backgroundImage, 'gradient');
+ };
+
+
+ tests['cssreflections'] = function() {
+ return testPropsAll('boxReflect');
+ };
+
+
+ tests['csstransforms'] = function() {
+ return !!testPropsAll('transform');
+ };
+
+
+ tests['csstransforms3d'] = function() {
+
+ var ret = !!testPropsAll('perspective');
+
+ if ( ret && 'webkitPerspective' in docElement.style ) {
+
+ injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
+ ret = node.offsetLeft === 9 && node.offsetHeight === 3;
+ });
+ }
+ return ret;
+ };
+
+
+ tests['csstransitions'] = function() {
+ return testPropsAll('transition');
+ };
+
+
+
+ tests['fontface'] = function() {
+ var bool;
+
+ injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) {
+ var style = document.getElementById('smodernizr'),
+ sheet = style.sheet || style.styleSheet,
+ cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
+
+ bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
+ });
+
+ return bool;
+ };
+
+ tests['generatedcontent'] = function() {
+ var bool;
+
+ injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {
+ bool = node.offsetHeight >= 3;
+ });
+
+ return bool;
+ };
+ tests['video'] = function() {
+ var elem = document.createElement('video'),
+ bool = false;
+
+ try {
+ if ( bool = !!elem.canPlayType ) {
+ bool = new Boolean(bool);
+ bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,'');
+
+ bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
+
+ bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
+ }
+
+ } catch(e) { }
+
+ return bool;
+ };
+
+ tests['audio'] = function() {
+ var elem = document.createElement('audio'),
+ bool = false;
+
+ try {
+ if ( bool = !!elem.canPlayType ) {
+ bool = new Boolean(bool);
+ bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
+ bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,'');
+
+ bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,'');
+ bool.m4a = ( elem.canPlayType('audio/x-m4a;') ||
+ elem.canPlayType('audio/aac;')) .replace(/^no$/,'');
+ }
+ } catch(e) { }
+
+ return bool;
+ };
+
+
+ tests['localstorage'] = function() {
+ try {
+ localStorage.setItem(mod, mod);
+ localStorage.removeItem(mod);
+ return true;
+ } catch(e) {
+ return false;
+ }
+ };
+
+ tests['sessionstorage'] = function() {
+ try {
+ sessionStorage.setItem(mod, mod);
+ sessionStorage.removeItem(mod);
+ return true;
+ } catch(e) {
+ return false;
+ }
+ };
+
+ tests['svg'] = function() {
+ return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
+ };
+
+ tests['inlinesvg'] = function() {
+ var div = document.createElement('div');
+ div.innerHTML = '';
+ return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
+ };
+
+ tests['smil'] = function() {
+ return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
+ };
+
+
+ tests['svgclippaths'] = function() {
+ return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
+ };
+
+ function webforms() {
+ Modernizr['input'] = (function( props ) {
+ for ( var i = 0, len = props.length; i < len; i++ ) {
+ attrs[ props[i] ] = !!(props[i] in inputElem);
+ }
+ if (attrs.list){
+ attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
+ }
+ return attrs;
+ })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
+ Modernizr['inputtypes'] = (function(props) {
+
+ for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
+
+ inputElem.setAttribute('type', inputElemType = props[i]);
+ bool = inputElem.type !== 'text';
+
+ if ( bool ) {
+
+ inputElem.value = smile;
+ inputElem.style.cssText = 'position:absolute;visibility:hidden;';
+
+ if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
+
+ docElement.appendChild(inputElem);
+ defaultView = document.defaultView;
+
+ bool = defaultView.getComputedStyle &&
+ defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
+ (inputElem.offsetHeight !== 0);
+
+ docElement.removeChild(inputElem);
+
+ } else if ( /^(search|tel)$/.test(inputElemType) ){
+ } else if ( /^(url|email)$/.test(inputElemType) ) {
+ bool = inputElem.checkValidity && inputElem.checkValidity() === false;
+
+ } else {
+ bool = inputElem.value != smile;
+ }
+ }
+
+ inputs[ props[i] ] = !!bool;
+ }
+ return inputs;
+ })('search tel url email datetime date month week time datetime-local number range color'.split(' '));
+ }
+ for ( var feature in tests ) {
+ if ( hasOwnProp(tests, feature) ) {
+ featureName = feature.toLowerCase();
+ Modernizr[featureName] = tests[feature]();
+
+ classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
+ }
+ }
+
+ Modernizr.input || webforms();
+
+
+ Modernizr.addTest = function ( feature, test ) {
+ if ( typeof feature == 'object' ) {
+ for ( var key in feature ) {
+ if ( hasOwnProp( feature, key ) ) {
+ Modernizr.addTest( key, feature[ key ] );
+ }
+ }
+ } else {
+
+ feature = feature.toLowerCase();
+
+ if ( Modernizr[feature] !== undefined ) {
+ return Modernizr;
+ }
+
+ test = typeof test == 'function' ? test() : test;
+
+ if (typeof enableClasses !== "undefined" && enableClasses) {
+ docElement.className += ' ' + (test ? '' : 'no-') + feature;
+ }
+ Modernizr[feature] = test;
+
+ }
+
+ return Modernizr;
+ };
+
+
+ setCss('');
+ modElem = inputElem = null;
+
+ ;(function(window, document) {
+ var options = window.html5 || {};
+
+ var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
+
+ var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
+
+ var supportsHtml5Styles;
+
+ var expando = '_html5shiv';
+
+ var expanID = 0;
+
+ var expandoData = {};
+
+ var supportsUnknownElements;
+
+ (function() {
+ try {
+ var a = document.createElement('a');
+ a.innerHTML = '';
+ supportsHtml5Styles = ('hidden' in a);
+
+ supportsUnknownElements = a.childNodes.length == 1 || (function() {
+ (document.createElement)('a');
+ var frag = document.createDocumentFragment();
+ return (
+ typeof frag.cloneNode == 'undefined' ||
+ typeof frag.createDocumentFragment == 'undefined' ||
+ typeof frag.createElement == 'undefined'
+ );
+ }());
+ } catch(e) {
+ supportsHtml5Styles = true;
+ supportsUnknownElements = true;
+ }
+
+ }()); function addStyleSheet(ownerDocument, cssText) {
+ var p = ownerDocument.createElement('p'),
+ parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
+
+ p.innerHTML = 'x';
+ return parent.insertBefore(p.lastChild, parent.firstChild);
+ }
+
+ function getElements() {
+ var elements = html5.elements;
+ return typeof elements == 'string' ? elements.split(' ') : elements;
+ }
+
+ function getExpandoData(ownerDocument) {
+ var data = expandoData[ownerDocument[expando]];
+ if (!data) {
+ data = {};
+ expanID++;
+ ownerDocument[expando] = expanID;
+ expandoData[expanID] = data;
+ }
+ return data;
+ }
+
+ function createElement(nodeName, ownerDocument, data){
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ if(supportsUnknownElements){
+ return ownerDocument.createElement(nodeName);
+ }
+ if (!data) {
+ data = getExpandoData(ownerDocument);
+ }
+ var node;
+
+ if (data.cache[nodeName]) {
+ node = data.cache[nodeName].cloneNode();
+ } else if (saveClones.test(nodeName)) {
+ node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
+ } else {
+ node = data.createElem(nodeName);
+ }
+
+ return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
+ }
+
+ function createDocumentFragment(ownerDocument, data){
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ if(supportsUnknownElements){
+ return ownerDocument.createDocumentFragment();
+ }
+ data = data || getExpandoData(ownerDocument);
+ var clone = data.frag.cloneNode(),
+ i = 0,
+ elems = getElements(),
+ l = elems.length;
+ for(;i0) {
if(self.menuDirection === 'down') {
@@ -146,7 +146,7 @@
settings.labels.splice(index,1);
}
var oldWidth=button.width();
- button.children('span').first().text(settings.labels.length > 0
+ button.children('span').first().text(settings.labels.length > 0
? settings.labels.join(', ')
: settings.title);
var newOuterWidth=Math.max((button.outerWidth()-2),settings.minOuterWidth)+'px';
@@ -193,7 +193,7 @@
return false;
}
var li=$(this).parent();
- var val = $(this).val()
+ var val = $(this).val();
var select=button.parent().next();
if(typeof settings.createCallback === 'function') {
var response = settings.createCallback(select, val);
@@ -217,7 +217,7 @@
select.append(option);
li.prev().children('input').prop('checked', true).trigger('change');
button.parent().data('preventHide',false);
- button.children('span').first().text(settings.labels.length > 0
+ button.children('span').first().text(settings.labels.length > 0
? settings.labels.join(', ')
: settings.title);
if(self.menuDirection === 'up') {
@@ -276,7 +276,7 @@
}
}
});
-
+
return span;
};
})( jQuery );
\ No newline at end of file
diff --git a/js/placeholder.polyfill.jquery.js b/js/placeholder.polyfill.jquery.js
deleted file mode 100644
index 16969eb8..00000000
--- a/js/placeholder.polyfill.jquery.js
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
-* HTML5 placeholder polyfill
-* @requires jQuery - tested with 1.6.2 but might as well work with older versions
-*
-* code: https://github.com/ginader/HTML5-placeholder-polyfill
-* please report issues at: https://github.com/ginader/HTML5-placeholder-polyfill/issues
-*
-* Copyright (c) 2012 Dirk Ginader (ginader.de)
-* Dual licensed under the MIT and GPL licenses:
-* http://www.opensource.org/licenses/mit-license.php
-* http://www.gnu.org/licenses/gpl.html
-*
-* Version: 2.0.3
-*
-* History:
-* * 1.0 initial release
-* * 1.1 added support for multiline placeholders in textareas
-* * 1.2 Allow label to wrap the input element by noah https://github.com/ginader/HTML5-placeholder-polyfill/pull/1
-* * 1.3 New option to read placeholder to Screenreaders. Turned on by default
-* * 1.4 made placeholder more rubust to allow labels being offscreen + added minified version of the 3rd party libs
-* * 1.5 emptying the native placeholder to prevent double rendering in Browsers with partial support
-* * 1.6 optional reformat when a textarea is being resized - requires http://benalman.com/projects/jquery-resize-plugin/
-* * 1.7 feature detection is now included in the polyfill so you can simply include it without the need for Modernizr
-* * 1.8 replacing the HTML5 Boilerplate .visuallyhidden technique with one that still allows the placeholder to be rendered
-* * 1.8.1 bugfix for implicit labels
-* * 1.9 New option "hideOnFocus" which, if set to false will mimic the behavior of mobile safari and chrome (remove label when typed instead of onfocus)
-* * 1.9.1 added reformat event on window resize
-* * 1.9.2 more flexible way to "fix" labels that are hidden using clip() thanks to grahambates: https://github.com/ginader/HTML5-placeholder-polyfill/issues/12
-* * 2.0 new easier configuration technique and new options forceApply and AutoInit and support for setters and getters
-* * 2.0.1 changed check for empty field so a space character is no longer ignored
-* * 2.0.2 allow rerun of the placeholder() to cover generated elements - existing polyfilled placeholder will be repositioned. Fixing: https://github.com/ginader/HTML5-placeholder-polyfill/issues/15
-* * 2.0.3 turn debugging of for production. fix https://github.com/ginader/HTML5-placeholder-polyfill/issues/18
-*/
-
-(function($) {
- var debug = false,
- animId;
- function showPlaceholderIfEmpty(input,options) {
- if( input.val() === '' ){
- input.data('placeholder').removeClass(options.hideClass);
- }else{
- input.data('placeholder').addClass(options.hideClass);
- }
- }
- function hidePlaceholder(input,options){
- input.data('placeholder').addClass(options.hideClass);
- }
- function positionPlaceholder(placeholder,input){
- var ta = input.is('textarea');
- placeholder.css({
- width : input.innerWidth()-(ta ? 20 : 4),
- height : input.innerHeight()-6,
- lineHeight : input.css('line-height'),
- whiteSpace : ta ? 'normal' : 'nowrap',
- overflow : 'hidden'
- }).offset(input.offset());
- }
- function startFilledCheckChange(input,options){
- var input = input,
- val = input.val();
- (function checkloop(){
- animId = requestAnimationFrame(checkloop);
- if(input.val() != val){
- hidePlaceholder(input,options);
- stopCheckChange();
- startEmptiedCheckChange(input,options);
- }
- })();
- }
- function startEmptiedCheckChange(input,options){
- var input = input,
- val = input.val();
- (function checkloop(){
- animId = requestAnimationFrame(checkloop);
- showPlaceholderIfEmpty(input,options);
- })();
- }
- function stopCheckChange(){
- cancelAnimationFrame(animId);
- }
- function log(msg){
- if(debug && window.console && window.console.log){
- window.console.log(msg);
- }
- }
-
- $.fn.placeHolder = function(config) {
- log('init placeHolder');
- var o = this;
- var l = $(this).length;
- this.options = $.extend({
- className: 'placeholder', // css class that is used to style the placeholder
- visibleToScreenreaders : true, // expose the placeholder text to screenreaders or not
- visibleToScreenreadersHideClass : 'placeholder-hide-except-screenreader', // css class is used to visually hide the placeholder
- visibleToNoneHideClass : 'placeholder-hide', // css class used to hide the placeholder for all
- hideOnFocus : false, // either hide the placeholder on focus or on type
- removeLabelClass : 'visuallyhidden', // remove this class from a label (to fix hidden labels)
- hiddenOverrideClass : 'visuallyhidden-with-placeholder', // replace the label above with this class
- forceHiddenOverride : true, // allow the replace of the removeLabelClass with hiddenOverrideClass or not
- forceApply : false, // apply the polyfill even for browser with native support
- autoInit : true // init automatically or not
- }, config);
- this.options.hideClass = this.options.visibleToScreenreaders ? this.options.visibleToScreenreadersHideClass : this.options.visibleToNoneHideClass;
- return $(this).each(function(index) {
- var input = $(this),
- text = input.attr('placeholder'),
- id = input.attr('id'),
- label,placeholder,titleNeeded,polyfilled;
- label = input.closest('label');
- input.removeAttr('placeholder');
- if(!label.length && !id){
- log('the input element with the placeholder needs an id!');
- return;
- }
- label = label.length ? label : $('label[for="'+id+'"]').first();
- if(!label.length){
- log('the input element with the placeholder needs a label!');
- return;
- }
- polyfilled = $(label).find('.placeholder');
- if(polyfilled.length) {
- //log('the input element already has a polyfilled placeholder!');
- positionPlaceholder(polyfilled,input);
- return input;
- }
-
- if(label.hasClass(o.options.removeLabelClass)){
- label.removeClass(o.options.removeLabelClass)
- .addClass(o.options.hiddenOverrideClass);
- }
-
- placeholder = $(''+text+'').appendTo(label);
-
- titleNeeded = (placeholder.width() > input.width());
- if(titleNeeded){
- placeholder.attr('title',text);
- }
- positionPlaceholder(placeholder,input);
- input.data('placeholder',placeholder);
- placeholder.data('input',placeholder);
- placeholder.click(function(){
- $(this).data('input').focus();
- });
- input.focusin(function() {
- if(!o.options.hideOnFocus && window.requestAnimationFrame){
- startFilledCheckChange(input,o.options);
- }else{
- hidePlaceholder(input,o.options);
- }
- });
- input.focusout(function(){
- showPlaceholderIfEmpty($(this),o.options);
- if(!o.options.hideOnFocus && window.cancelAnimationFrame){
- stopCheckChange();
- }
- });
- showPlaceholderIfEmpty(input,o.options);
-
- // reformat on window resize and optional reformat on font resize - requires: http://www.tomdeater.com/jquery/onfontresize/
- $(document).bind("fontresize resize", function(){
- positionPlaceholder(placeholder,input);
- });
-
- // optional reformat when a textarea is being resized - requires http://benalman.com/projects/jquery-resize-plugin/
- if($.event.special.resize){
- $("textarea").bind("resize", function(e){
- positionPlaceholder(placeholder,input);
- });
- }else{
- // we simply disable the resizeablilty of textareas when we can't react on them resizing
- $("textarea").css('resize','none');
- }
-
- if(index >= l-1){
- $.attrHooks.placeholder = {
- get: function(elem) {
- if (elem.nodeName.toLowerCase() == 'input' || elem.nodeName.toLowerCase() == 'textarea') {
- if( $(elem).data('placeholder') ){
- // has been polyfilled
- return $( $(elem).data('placeholder') ).text();
- }else{
- // native / not yet polyfilled
- return $(elem)[0].placeholder;
- }
-
- }else{
- return undefined;
- }
- },
- set: function(elem, value){
- return $( $(elem).data('placeholder') ).text(value);
- }
- };
- }
- });
-
-
-
- };
- $(function(){
- var config = window.placeHolderConfig || {};
- if(config.autoInit === false){
- log('placeholder:abort because autoInit is off');
- return
- }
- if('placeholder' in $('')[0] && !config.forceApply){ // don't run the polyfill when the browser has native support
- log('placeholder:abort because browser has native support');
- return;
- }
- $('input[placeholder], textarea[placeholder]').placeHolder(config);
- });
-})(jQuery);
\ No newline at end of file
diff --git a/js/placeholder_polyfill.jquery.js b/js/placeholder_polyfill.jquery.js
new file mode 100644
index 00000000..9f42284f
--- /dev/null
+++ b/js/placeholder_polyfill.jquery.js
@@ -0,0 +1,1005 @@
+
+
+
+
+
+
+
+
+ HTML5-placeholder-polyfill/src/placeholder_polyfill.jquery.js at master · ginader/HTML5-placeholder-polyfill · GitHub
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+
+ |
+
+ /** * HTML5 placeholder polyfill * @requires jQuery - tested with 1.6.2 but might as well work with older versions * * code: https://github.com/ginader/HTML5-placeholder-polyfill * please report issues at: https://github.com/ginader/HTML5-placeholder-polyfill/issues * * Copyright (c) 2012 Dirk Ginader (ginader.de) * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * Version: 2.0.6 * */
(function($) { var debug = false, animId; function showPlaceholderIfEmpty(input,options) { if( input.val() === '' ){ input.data('placeholder').removeClass(options.hideClass); }else{ input.data('placeholder').addClass(options.hideClass); } } function hidePlaceholder(input,options){ input.data('placeholder').addClass(options.hideClass); } function positionPlaceholder(placeholder,input){ var ta = input.is('textarea');
// Determine if we need to shift the header down more. var offset = input.offset(); if (input.css('padding') && input.css('padding') !== '0px') { var padding = input.css('padding').split(' '); offset.top += Number(padding[0].replace('px', '')); offset.left += Number(padding[padding.length - 1].replace('px', '')); } else { if (input.css('padding-top') && input.css('padding-top') !== '0px') { offset.top += Number(input.css('padding-top').replace('px', '')); } if (input.css('padding-left') && input.css('padding-left') !== '0px') { offset.left += Number(input.css('padding-left').replace('px', '')); } }
placeholder.css({ width : input.innerWidth()-(ta ? 20 : 4), height : input.innerHeight()-6, lineHeight : input.css('line-height'), whiteSpace : ta ? 'normal' : 'nowrap', overflow : 'hidden' }).offset(offset); } function startFilledCheckChange(input,options){ var val = input.val(); (function checkloop(){ animId = requestAnimationFrame(checkloop); if(input.val() !== val){ hidePlaceholder(input,options); stopCheckChange(); startEmptiedCheckChange(input,options); } }()); } function startEmptiedCheckChange(input,options){ (function checkloop(){ animId = requestAnimationFrame(checkloop); showPlaceholderIfEmpty(input,options); }()); } function stopCheckChange(){ cancelAnimationFrame(animId); } function log(msg){ if(debug && window.console && window.console.log){ window.console.log(msg); } }
$.fn.placeHolder = function(config) { log('init placeHolder'); var o = this; var l = $(this).length; this.options = $.extend({ className: 'placeholder', // css class that is used to style the placeholder visibleToScreenreaders : true, // expose the placeholder text to screenreaders or not visibleToScreenreadersHideClass : 'placeholder-hide-except-screenreader', // css class is used to visually hide the placeholder visibleToNoneHideClass : 'placeholder-hide', // css class used to hide the placeholder for all hideOnFocus : false, // either hide the placeholder on focus or on type removeLabelClass : 'visuallyhidden', // remove this class from a label (to fix hidden labels) hiddenOverrideClass : 'visuallyhidden-with-placeholder', // replace the label above with this class forceHiddenOverride : true, // allow the replace of the removeLabelClass with hiddenOverrideClass or not forceApply : false, // apply the polyfill even for browser with native support autoInit : true // init automatically or not }, config); this.options.hideClass = this.options.visibleToScreenreaders ? this.options.visibleToScreenreadersHideClass : this.options.visibleToNoneHideClass; return $(this).each(function(index) { var input = $(this), text = input.attr('placeholder'), id = input.attr('id'), label,placeholder,titleNeeded,polyfilled; if(text === "" || text === undefined) { text = input[0].attributes["placeholder"].value; } label = input.closest('label'); input.removeAttr('placeholder'); if(!label.length && !id){ log('the input element with the placeholder needs an id!'); return; } label = label.length ? label : $('label[for="'+id+'"]').first(); if(!label.length){ log('the input element with the placeholder needs a label!'); return; } polyfilled = $(label).find('.placeholder'); if(polyfilled.length) { //log('the input element already has a polyfilled placeholder!'); positionPlaceholder(polyfilled,input); polyfilled.text(text); return input; } if(label.hasClass(o.options.removeLabelClass)){ label.removeClass(o.options.removeLabelClass) .addClass(o.options.hiddenOverrideClass); }
placeholder = $('<span>').addClass(o.options.className).text(text).appendTo(label);
titleNeeded = (placeholder.width() > input.width()); if(titleNeeded){ placeholder.attr('title',text); } positionPlaceholder(placeholder,input); input.data('placeholder',placeholder); placeholder.data('input',placeholder); placeholder.click(function(){ $(this).data('input').focus(); }); input.focusin(function() { if(!o.options.hideOnFocus && window.requestAnimationFrame){ startFilledCheckChange(input,o.options); }else{ hidePlaceholder(input,o.options); } }); input.focusout(function(){ showPlaceholderIfEmpty($(this),o.options); if(!o.options.hideOnFocus && window.cancelAnimationFrame){ stopCheckChange(); } }); showPlaceholderIfEmpty(input,o.options);
// reformat on window resize and optional reformat on font resize - requires: http://www.tomdeater.com/jquery/onfontresize/ $(document).bind("fontresize resize", function(){ positionPlaceholder(placeholder,input); });
// optional reformat when a textarea is being resized - requires http://benalman.com/projects/jquery-resize-plugin/ if($.event.special.resize){ $("textarea").bind("resize", function(e){ positionPlaceholder(placeholder,input); }); }else{ // we simply disable the resizeablilty of textareas when we can't react on them resizing $("textarea").css('resize','none'); }
if(index >= l-1){ $.attrHooks.placeholder = { get: function(elem) { if (elem.nodeName.toLowerCase() === 'input' || elem.nodeName.toLowerCase() === 'textarea') { if( $(elem).data('placeholder') ){ // has been polyfilled return $( $(elem).data('placeholder') ).text(); }else{ // native / not yet polyfilled return $(elem)[0].placeholder; } }else{ return undefined; } }, set: function(elem, value){ return $( $(elem).data('placeholder') ).text(value); } }; } });
}; $(function(){ var config = window.placeHolderConfig || {}; if(config.autoInit === false){ log('placeholder:abort because autoInit is off'); return; } if(('placeholder' in $('<input>')[0] || 'placeHolder' in $('<input>')[0]) && !config.forceApply){ // don't run the polyfill when the browser has native support log('placeholder:abort because browser has native support'); return; } $('input[placeholder], textarea[placeholder]').placeHolder(config); }); }(jQuery));
+ |
+
+
+
+
+
+
+
+
+
Jump to Line
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Something went wrong with that request. Please try again.
+
+
+
+
+
+
+
+
+
+
diff --git a/js/placeholder_polyfill.jquery.min.combo.js b/js/placeholder_polyfill.jquery.min.combo.js
new file mode 100644
index 00000000..3e3a3dfd
--- /dev/null
+++ b/js/placeholder_polyfill.jquery.min.combo.js
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) 2008 Tom Deater (http://www.tomdeater.com)
+ * Licensed under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+jQuery.onFontResize=(function(a){a(document).ready(function(){var c=a("").attr("id","frame-onFontResize"+Date.parse(new Date)).addClass("div-onfontresize").css({width:"100em",height:"10px",position:"absolute",borderWidth:0,top:"-5000px",left:"-5000px"}).appendTo("body");
+if(a.browser.msie){c.bind("resize",function(){a.onFontResize.trigger(c[0].offsetWidth/100);});}else{var b=c[0].contentWindow||c[0].contentDocument||c[0].document;
+b=b.document||b;b.open();b.write('