diff --git a/css/bootstrap-select.css b/css/bootstrap-select.css new file mode 100644 index 0000000..a21033f --- /dev/null +++ b/css/bootstrap-select.css @@ -0,0 +1,278 @@ +/*! + * bootstrap-select v1.3.7 + * http://silviomoreto.github.io/bootstrap-select/ + * + * Copyright 2013 bootstrap-select + * Licensed under the MIT license + */ + +.bootstrap-select.btn-group, +.bootstrap-select.btn-group[class*="span"] { + float: none; + display: inline-block; + margin-bottom: 10px; + margin-left: 0; +} +.form-search .bootstrap-select.btn-group, +.form-inline .bootstrap-select.btn-group, +.form-horizontal .bootstrap-select.btn-group { + margin-bottom: 0; +} + +.bootstrap-select.form-control { + margin-bottom: 0; + padding: 0; + border: none; +} + +.bootstrap-select.btn-group.pull-right, +.bootstrap-select.btn-group[class*="span"].pull-right, +.row-fluid .bootstrap-select.btn-group[class*="span"].pull-right { + float: right; +} + +.input-append .bootstrap-select.btn-group { + margin-left: -1px; +} + +.input-prepend .bootstrap-select.btn-group { + margin-right: -1px; +} + +.bootstrap-select:not([class*="span"]):not([class*="col-"]):not([class*="form-control"]) { + width: 220px; +} + +.bootstrap-select { + /*width: 220px\9; IE8 and below*/ + width: 220px\0; /*IE9 and below*/ +} + +.bootstrap-select.form-control:not([class*="span"]) { + width: 100%; +} + +.bootstrap-select > .btn { + width: 100%; +} + +.error .bootstrap-select .btn { + border: 1px solid #b94a48; +} + + +.dropdown-menu { + z-index: 2000; +} + +.bootstrap-select.show-menu-arrow.open > .btn { + z-index: 2051; +} + +.bootstrap-select .btn:focus { + outline: thin dotted #333333 !important; + outline: 5px auto -webkit-focus-ring-color !important; + outline-offset: -2px; +} + +.bootstrap-select.btn-group .btn .filter-option { + overflow: hidden; + position: absolute; + left: 12px; + right: 25px; + text-align: left; +} + +.bootstrap-select.btn-group .btn .caret { + position: absolute; + top: 50%; + right: 12px; + margin-top: -2px; + vertical-align: middle; +} + +.bootstrap-select.btn-group > .disabled, +.bootstrap-select.btn-group .dropdown-menu li.disabled > a { + cursor: not-allowed; +} + +.bootstrap-select.btn-group > .disabled:focus { + outline: none !important; +} + +.bootstrap-select.btn-group[class*="span"] .btn { + width: 100%; +} + +.bootstrap-select.btn-group .dropdown-menu { + min-width: 100%; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.bootstrap-select.btn-group .dropdown-menu.inner { + position: static; + border: 0; + padding: 0; + margin: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.bootstrap-select.btn-group .dropdown-menu dt { + display: block; + padding: 3px 20px; + cursor: default; +} + +.bootstrap-select.btn-group .div-contain { + overflow: hidden; +} + +.bootstrap-select.btn-group .dropdown-menu li { + position: relative; +} + +.bootstrap-select.btn-group .dropdown-menu li > a.opt { + position: relative; + padding-left: 35px; +} + +.bootstrap-select.btn-group .dropdown-menu li > a { + cursor: pointer; +} + +.bootstrap-select.btn-group .dropdown-menu li > dt small { + font-weight: normal; +} + +.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a i.check-mark { + display: inline-block; + position: absolute; + right: 15px; + margin-top: 2.5px; +} + +.bootstrap-select.btn-group .dropdown-menu li a i.check-mark { + display: none; +} + +.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text { + margin-right: 34px; +} + +.bootstrap-select.btn-group .dropdown-menu li small { + padding-left: 0.5em; +} + +.bootstrap-select.btn-group .dropdown-menu li:not(.disabled) > a:hover small, +.bootstrap-select.btn-group .dropdown-menu li:not(.disabled) > a:focus small, +.bootstrap-select.btn-group .dropdown-menu li.active:not(.disabled) > a small { + color: #64b1d8; + color: rgba(255,255,255,0.4); +} + +.bootstrap-select.btn-group .dropdown-menu li > dt small { + font-weight: normal; +} + +.bootstrap-select.show-menu-arrow .dropdown-toggle:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #CCC; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + bottom: -4px; + left: 9px; + display: none; +} + +.bootstrap-select.show-menu-arrow .dropdown-toggle:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + position: absolute; + bottom: -4px; + left: 10px; + display: none; +} + +.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before { + bottom: auto; + top: -3px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2); +} + +.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after { + bottom: auto; + top: -3px; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before { + right: 12px; + left: auto; +} +.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after { + right: 13px; + left: auto; +} + +.bootstrap-select.show-menu-arrow.open > .dropdown-toggle:before, +.bootstrap-select.show-menu-arrow.open > .dropdown-toggle:after { + display: block; +} + +.bootstrap-select.btn-group .no-results { + padding: 3px; + background: #f5f5f5; + margin: 0 5px; +} + +.mobile-device { + position: absolute; + top: 0; + left: 0; + display: block !important; + width: 100%; + height: 100% !important; + opacity: 0; +} + +.bootstrap-select.fit-width { + width: auto !important; +} + +.bootstrap-select.btn-group.fit-width .btn .filter-option { + position: static; +} + +.bootstrap-select.btn-group.fit-width .btn .caret { + position: static; + top: auto; + margin-top: -1px; +} + +.control-group.error .bootstrap-select .dropdown-toggle{ + border-color: #b94a48; +} + +.bootstrap-select-searchbox { + padding: 4px 8px; +} + +.bootstrap-select-searchbox input { + margin-bottom: 0; +} diff --git a/index.html b/index.html index 6657082..02b4e60 100644 --- a/index.html +++ b/index.html @@ -13,6 +13,9 @@ + + + Quora Archive @@ -22,7 +25,7 @@
Select bucket - +
@@ -168,8 +171,6 @@ - - @@ -178,5 +179,4 @@ - \ No newline at end of file diff --git a/js/Indexscript.js b/js/Indexscript.js index 0b99f94..b2bb133 100644 --- a/js/Indexscript.js +++ b/js/Indexscript.js @@ -40,7 +40,7 @@ function checkUserLoggedIn(){ storage.get(data_key, function(items) { var data_version = items[data_key]; - if (typeof data_version == 'undefined' || data_version["data_version"] != "v2") { + if (typeof data_version == 'undefined' || data_version["data_version"] != "v2.2") { migrateArchiveData(user); return -1; } @@ -50,7 +50,8 @@ function checkUserLoggedIn(){ populateBuckets(); - populateClassifyAnswersMenu(); + //Commented By Rumit, as sometimes it was getting called before populateBuckets async call completes, resulting into blank classify ddl. + //populateClassifyAnswersMenu(); populateArchiveStatus(); // populates the archive status div. populateUserInformation(); @@ -83,7 +84,7 @@ function populateBuckets() { if (typeof buckets == 'undefined') // no buckets. return ; - buckets = buckets.split(";"); + //buckets = buckets.split(";"); global_buckets = buckets; populateClassifyAnswersMenu(); @@ -125,7 +126,8 @@ function populateClassifyAnswersMenu () { $('#answerBucketDD').append(temp_html); } - + console.log(global_buckets); + $("#answerBucketDD").selectpicker(); } @@ -259,9 +261,24 @@ function contentPopulate(bucket) { tempAnswerBucket = userLinks[tempAnswerLink]["bucket"]; // skips answers that do not match the specified bucket - if (bucket.toLowerCase() != "all" && tempAnswerBucket.toLowerCase() != bucket.toLowerCase()) - continue; - + if (bucket.toLowerCase() != "all") {//&& tempAnswerBucket.toLowerCase() != bucket.toLowerCase()) + var found = false; + + if(bucket == '') { + found = (tempAnswerBucket.length == 0); + } + + for(var b in tempAnswerBucket){ + if(tempAnswerBucket[b].toLowerCase() == bucket.toLowerCase()){ + found = true; + break; + } + } + if(!found) { + continue; + } + } + if (tempAnswerLink.match(/(http|https):\/\/[\w\-+]+\.quora\.com\/[\w\-+]+/i) != null || tempAnswerLink.indexOf('answer') == -1) // if the link is that of a post displayBlogLink(tempAnswerLink); else diff --git a/js/add_archive_button.js b/js/add_archive_button.js index ff92087..5ebe2b6 100644 --- a/js/add_archive_button.js +++ b/js/add_archive_button.js @@ -144,7 +144,7 @@ function addLink(element, link) { } - userLinks[link] = {"bucket": ""}; // add a new entry to existing links. Key= link, Value: Bucket + userLinks[link] = {"bucket": []}; // add a new entry to existing links. Key= link, Value: Bucket var userDict = {}; // temporary variable created to be able to use chrome local storage @@ -176,7 +176,7 @@ function loggedUser() cache: false, dataType: "text", success: function(html) - { + { try { var result = JSON.parse(html.match(/{.*}/)); @@ -186,7 +186,7 @@ function loggedUser() { console.log(ex); } - }, + }, error: function(jqXHR, textStatus, errorThrown) { console.log(errorThrown) diff --git a/js/bootstrap-select.js b/js/bootstrap-select.js new file mode 100644 index 0000000..249388f --- /dev/null +++ b/js/bootstrap-select.js @@ -0,0 +1,850 @@ +/*! + * bootstrap-select v1.3.7 + * http://silviomoreto.github.io/bootstrap-select/ + * + * Copyright 2013 bootstrap-select + * Licensed under the MIT license + */ + +!function($) { + + "use strict"; + + $.expr[":"].icontains = function(obj, index, meta) { + return $(obj).text().toUpperCase().indexOf(meta[3].toUpperCase()) >= 0; + }; + + var Selectpicker = function(element, options, e) { + if (e) { + e.stopPropagation(); + e.preventDefault(); + } + this.$element = $(element); + this.$newElement = null; + this.$button = null; + this.$menu = null; + + //Merge defaults, options and data-attributes to make our options + this.options = $.extend({}, $.fn.selectpicker.defaults, this.$element.data(), typeof options == 'object' && options); + + //If we have no title yet, check the attribute 'title' (this is missed by jq as its not a data-attribute + if (this.options.title == null) { + this.options.title = this.$element.attr('title'); + } + + //Expose public methods + this.val = Selectpicker.prototype.val; + this.render = Selectpicker.prototype.render; + this.refresh = Selectpicker.prototype.refresh; + this.setStyle = Selectpicker.prototype.setStyle; + this.selectAll = Selectpicker.prototype.selectAll; + this.deselectAll = Selectpicker.prototype.deselectAll; + this.init(); + }; + + Selectpicker.prototype = { + + constructor: Selectpicker, + + init: function() { + this.$element.hide(); + this.multiple = this.$element.prop('multiple'); + var id = this.$element.attr('id'); + this.$newElement = this.createView(); + this.$element.after(this.$newElement); + this.$menu = this.$newElement.find('> .dropdown-menu'); + this.$button = this.$newElement.find('> button'); + this.$searchbox = this.$newElement.find('input'); + + if (id !== undefined) { + var that = this; + this.$button.attr('data-id', id); + $('label[for="' + id + '"]').click(function(e) { + e.preventDefault(); + that.$button.focus(); + }); + } + + this.checkDisabled(); + this.clickListener(); + if (this.options.liveSearch) { + this.liveSearchListener(); + } + this.render(); + this.liHeight(); + this.setStyle(); + this.setWidth(); + if (this.options.container) { + this.selectPosition(); + } + this.$menu.data('this', this); + this.$newElement.data('this', this); + }, + + createDropdown: function() { + //If we are multiple, then add the show-tick class by default + var multiple = this.multiple ? ' show-tick' : ''; + var header = this.options.header ? '
' + this.options.header + '
' : ''; + var searchbox = this.options.liveSearch ? '' : ''; + var drop = + "
" + + "" + + "" + + "
"; + + return $(drop); + }, + + createView: function() { + var $drop = this.createDropdown(); + var $li = this.createLi(); + $drop.find('ul').append($li); + return $drop; + }, + + reloadLi: function() { + //Remove all children. + this.destroyLi(); + //Re build + var $li = this.createLi(); + this.$menu.find('ul').append( $li ); + }, + + destroyLi: function() { + this.$menu.find('li').remove(); + }, + + createLi: function() { + var that = this, + _liA = [], + _liHtml = ''; + + this.$element.find('option').each(function() { + var $this = $(this); + + //Get the class and text for the option + var optionClass = $this.attr("class") || ''; + var inline = $this.attr("style") || ''; + var text = $this.data('content') ? $this.data('content') : $this.html(); + var subtext = $this.data('subtext') !== undefined ? '' + $this.data('subtext') + '' : ''; + var icon = $this.data('icon') !== undefined ? ' ' : ''; + if (icon !== '' && ($this.is(':disabled') || $this.parent().is(':disabled'))) { + icon = ''+icon+''; + } + + if (!$this.data('content')) { + //Prepend any icon and append any subtext to the main text. + text = icon + '' + text + subtext + ''; + } + + if (that.options.hideDisabled && ($this.is(':disabled') || $this.parent().is(':disabled'))) { + _liA.push(''); + } else if ($this.parent().is('optgroup') && $this.data('divider') !== true) { + if ($this.index() == 0) { + //Get the opt group label + var label = $this.parent().attr('label'); + var labelSubtext = $this.parent().data('subtext') !== undefined ? ''+$this.parent().data('subtext')+'' : ''; + var labelIcon = $this.parent().data('icon') ? ' ' : ''; + label = labelIcon + '' + label + labelSubtext + ''; + + if ($this[0].index != 0) { + _liA.push( + '
'+ + '
'+label+'
'+ + that.createA(text, "opt " + optionClass, inline ) + ); + } else { + _liA.push( + '
'+label+'
'+ + that.createA(text, "opt " + optionClass, inline )); + } + } else { + _liA.push(that.createA(text, "opt " + optionClass, inline )); + } + } else if ($this.data('divider') === true) { + _liA.push('
'); + } else if ($(this).data('hidden') === true) { + _liA.push(''); + } else { + _liA.push(that.createA(text, optionClass, inline )); + } + }); + + $.each(_liA, function(i, item) { + _liHtml += "
  • " + item + "
  • "; + }); + + //If we are not multiple, and we dont have a selected item, and we dont have a title, select the first element so something is set in the button + if (!this.multiple && this.$element.find('option:selected').length==0 && !this.options.title) { + this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected'); + } + + return $(_liHtml); + }, + + createA: function(text, classes, inline) { + return '' + + text + + '' + + ''; + }, + + render: function() { + var that = this; + + //Update the LI to match the SELECT + this.$element.find('option').each(function(index) { + that.setDisabled(index, $(this).is(':disabled') || $(this).parent().is(':disabled') ); + that.setSelected(index, $(this).is(':selected') ); + }); + + this.tabIndex(); + + var selectedItems = this.$element.find('option:selected').map(function() { + var $this = $(this); + var icon = $this.data('icon') && that.options.showIcon ? ' ' : ''; + var subtext; + if (that.options.showSubtext && $this.attr('data-subtext') && !that.multiple) { + subtext = ' '+$this.data('subtext') +''; + } else { + subtext = ''; + } + if ($this.data('content') && that.options.showContent) { + return $this.data('content'); + } else if ($this.attr('title') != undefined) { + return $this.attr('title'); + } else { + return icon + $this.html() + subtext; + } + }).toArray(); + + //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled + //Convert all the values into a comma delimited string + var title = !this.multiple ? selectedItems[0] : selectedItems.join(", "); + + //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc.. + if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) { + var max = this.options.selectedTextFormat.split(">"); + var notDisabled = this.options.hideDisabled ? ':not([disabled])' : ''; + if ( (max.length>1 && selectedItems.length > max[1]) || (max.length==1 && selectedItems.length>=2)) { + title = this.options.countSelectedText.replace('{0}', selectedItems.length).replace('{1}', this.$element.find('option:not([data-divider="true"]):not([data-hidden="true"])'+notDisabled).length); + } + } + + //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text + if (!title) { + title = this.options.title != undefined ? this.options.title : this.options.noneSelectedText; + } + + this.$newElement.find('.filter-option').html(title); + }, + + setStyle: function(style, status) { + if (this.$element.attr('class')) { + this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device/gi, '')); + } + + var buttonClass = style ? style : this.options.style; + + if (status == 'add') { + this.$button.addClass(buttonClass); + } else if (status == 'remove') { + this.$button.removeClass(buttonClass); + } else { + this.$button.removeClass(this.options.style); + this.$button.addClass(buttonClass); + } + }, + + liHeight: function() { + var $selectClone = this.$menu.parent().clone().appendTo('body'), + $menuClone = $selectClone.addClass('open').find('> .dropdown-menu'), + liHeight = $menuClone.find('li > a').outerHeight(), + headerHeight = this.options.header ? $menuClone.find('.popover-title').outerHeight() : 0, + searchHeight = this.options.liveSearch ? $menuClone.find('.bootstrap-select-searchbox').outerHeight() : 0; + + $selectClone.remove(); + + this.$newElement + .data('liHeight', liHeight) + .data('headerHeight', headerHeight) + .data('searchHeight', searchHeight); + }, + + setSize: function() { + var that = this, + menu = this.$menu, + menuInner = menu.find('.inner'), + selectHeight = this.$newElement.outerHeight(), + liHeight = this.$newElement.data('liHeight'), + headerHeight = this.$newElement.data('headerHeight'), + searchHeight = this.$newElement.data('searchHeight'), + divHeight = menu.find('li .divider').outerHeight(true), + menuPadding = parseInt(menu.css('padding-top')) + + parseInt(menu.css('padding-bottom')) + + parseInt(menu.css('border-top-width')) + + parseInt(menu.css('border-bottom-width')), + notDisabled = this.options.hideDisabled ? ':not(.disabled)' : '', + $window = $(window), + menuExtras = menuPadding + parseInt(menu.css('margin-top')) + parseInt(menu.css('margin-bottom')) + 2, + menuHeight, + selectOffsetTop, + selectOffsetBot, + posVert = function() { + selectOffsetTop = that.$newElement.offset().top - $window.scrollTop(); + selectOffsetBot = $window.height() - selectOffsetTop - selectHeight; + }; + posVert(); + if (this.options.header) menu.css('padding-top', 0); + + if (this.options.size == 'auto') { + var getSize = function() { + var minHeight; + posVert(); + menuHeight = selectOffsetBot - menuExtras; + if (that.options.dropupAuto) { + that.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && ((menuHeight - menuExtras) < menu.height())); + } + if (that.$newElement.hasClass('dropup')) { + menuHeight = selectOffsetTop - menuExtras; + } + if ((menu.find('li').length + menu.find('dt').length) > 3) { + minHeight = liHeight*3 + menuExtras - 2; + } else { + minHeight = 0; + } + menu.css({'max-height' : menuHeight + 'px', 'overflow' : 'hidden', 'min-height' : minHeight + 'px'}); + menuInner.css({'max-height' : menuHeight - headerHeight - searchHeight- menuPadding + 'px', 'overflow-y' : 'auto', 'min-height' : minHeight - menuPadding + 'px'}); + }; + getSize(); + $(window).resize(getSize); + $(window).scroll(getSize); + } else if (this.options.size && this.options.size != 'auto' && menu.find('li'+notDisabled).length > this.options.size) { + var optIndex = menu.find("li"+notDisabled+" > *").filter(':not(.div-contain)').slice(0,this.options.size).last().parent().index(); + var divLength = menu.find("li").slice(0,optIndex + 1).find('.div-contain').length; + menuHeight = liHeight*this.options.size + divLength*divHeight + menuPadding; + if (that.options.dropupAuto) { + this.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && (menuHeight < menu.height())); + } + menu.css({'max-height' : menuHeight + headerHeight + searchHeight + 'px', 'overflow' : 'hidden'}); + menuInner.css({'max-height' : menuHeight - menuPadding + 'px', 'overflow-y' : 'auto'}); + } + }, + + setWidth: function() { + if (this.options.width == 'auto') { + this.$menu.css('min-width', '0'); + + // Get correct width if element hidden + var selectClone = this.$newElement.clone().appendTo('body'); + var ulWidth = selectClone.find('> .dropdown-menu').css('width'); + selectClone.remove(); + + this.$newElement.css('width', ulWidth); + } else if (this.options.width == 'fit') { + // Remove inline min-width so width can be changed from 'auto' + this.$menu.css('min-width', ''); + this.$newElement.css('width', '').addClass('fit-width'); + } else if (this.options.width) { + // Remove inline min-width so width can be changed from 'auto' + this.$menu.css('min-width', ''); + this.$newElement.css('width', this.options.width); + } else { + // Remove inline min-width/width so width can be changed + this.$menu.css('min-width', ''); + this.$newElement.css('width', ''); + } + // Remove fit-width class if width is changed programmatically + if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') { + this.$newElement.removeClass('fit-width'); + } + }, + + selectPosition: function() { + var that = this, + drop = "
    ", + $drop = $(drop), + pos, + actualHeight, + getPlacement = function($element) { + $drop.addClass($element.attr('class')).toggleClass('dropup', $element.hasClass('dropup')); + pos = $element.offset(); + actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight; + $drop.css({'top' : pos.top + actualHeight, 'left' : pos.left, 'width' : $element[0].offsetWidth, 'position' : 'absolute'}); + }; + this.$newElement.on('click', function() { + getPlacement($(this)); + $drop.appendTo(that.options.container); + $drop.toggleClass('open', !$(this).hasClass('open')); + $drop.append(that.$menu); + }); + $(window).resize(function() { + getPlacement(that.$newElement); + }); + $(window).on('scroll', function() { + getPlacement(that.$newElement); + }); + $('html').on('click', function(e) { + if ($(e.target).closest(that.$newElement).length < 1) { + $drop.removeClass('open'); + } + }); + }, + + mobile: function() { + this.$element.addClass('mobile-device').appendTo(this.$newElement); + if (this.options.container) this.$menu.hide(); + }, + + refresh: function() { + this.reloadLi(); + this.render(); + this.setWidth(); + this.setStyle(); + this.checkDisabled(); + this.liHeight(); + }, + + update: function() { + this.reloadLi(); + this.setWidth(); + this.setStyle(); + this.checkDisabled(); + this.liHeight(); + }, + + setSelected: function(index, selected) { + this.$menu.find('li').eq(index).toggleClass('selected', selected); + }, + + setDisabled: function(index, disabled) { + if (disabled) { + this.$menu.find('li').eq(index).addClass('disabled').find('a').attr('href', '#').attr('tabindex', -1); + } else { + this.$menu.find('li').eq(index).removeClass('disabled').find('a').removeAttr('href').attr('tabindex', 0); + } + }, + + isDisabled: function() { + return this.$element.is(':disabled'); + }, + + checkDisabled: function() { + var that = this; + + if (this.isDisabled()) { + this.$button.addClass('disabled').attr('tabindex', -1); + } else { + if (this.$button.hasClass('disabled')) { + this.$button.removeClass('disabled'); + } + + if (this.$button.attr('tabindex') == -1) { + if (!this.$element.data('tabindex')) this.$button.removeAttr('tabindex'); + } + } + + this.$button.click(function() { + return !that.isDisabled(); + }); + }, + + tabIndex: function() { + if (this.$element.is('[tabindex]')) { + this.$element.data('tabindex', this.$element.attr("tabindex")); + this.$button.attr('tabindex', this.$element.data('tabindex')); + } + }, + + clickListener: function() { + var that = this; + + $('body').on('touchstart.dropdown', '.dropdown-menu', function(e) { + e.stopPropagation(); + }); + + this.$newElement.on('click', function() { + that.setSize(); + if (!that.options.liveSearch && !that.multiple) { + setTimeout(function() { + that.$menu.find('.selected a').focus(); + }, 10); + } + }); + + this.$menu.on('click', 'li a', function(e) { + var clickedIndex = $(this).parent().index(), + prevValue = that.$element.val(), + prevIndex = that.$element.prop('selectedIndex'); + + //Dont close on multi choice menu + if (that.multiple) { + e.stopPropagation(); + } + + e.preventDefault(); + + //Dont run if we have been disabled + if (!that.isDisabled() && !$(this).parent().hasClass('disabled')) { + var $options = that.$element.find('option'); + var $option = $options.eq(clickedIndex); + + //Deselect all others if not multi select box + if (!that.multiple) { + $options.prop('selected', false); + $option.prop('selected', true); + } + //Else toggle the one we have chosen if we are multi select. + else { + var state = $option.prop('selected'); + + $option.prop('selected', !state); + } + + if (!that.multiple) { + that.$button.focus(); + } else if (that.options.liveSearch) { + that.$searchbox.focus(); + } + + // Trigger select 'change' + if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) { + that.$element.change(); + } + } + }); + + this.$menu.on('click', 'li.disabled a, li dt, li .div-contain, .popover-title, .popover-title :not(.close)', function(e) { + if (e.target == this) { + e.preventDefault(); + e.stopPropagation(); + if (!that.options.liveSearch) { + that.$button.focus(); + } else { + that.$searchbox.focus(); + } + } + }); + + this.$menu.on('click', '.popover-title .close', function() { + that.$button.focus(); + }); + + this.$searchbox.on('click', function(e) { + e.stopPropagation(); + }); + + this.$element.change(function() { + that.render(); + }); + }, + + liveSearchListener: function() { + var that = this, + no_results = $('
  • '); + + this.$newElement.on('click.dropdown.data-api', function() { + that.$menu.find('.active').removeClass('active'); + if (!!that.$searchbox.val()) { + that.$searchbox.val(''); + that.$menu.find('li').show(); + no_results.remove(); + } + if (!that.multiple) that.$menu.find('.selected').addClass('active'); + setTimeout(function() { + that.$searchbox.focus(); + }, 10); + }); + + this.$searchbox.on('input propertychange', function() { + if (that.$searchbox.val()) { + that.$menu.find('li').show().not(':icontains(' + that.$searchbox.val() + ')').hide(); + + if (!that.$menu.find('li').filter(':visible:not(.no-results)').length) { + no_results.remove(); + no_results.html('No results match "'+ that.$searchbox.val() + '"').show(); + that.$menu.find('li').last().after(no_results); + } else { + no_results.remove(); + } + + } else { + that.$menu.find('li').show(); + } + that.$menu.find('li.active').removeClass('active'); + that.$menu.find('li').filter(':visible:not(.divider)').eq(0).addClass('active').find('a').focus(); + $(this).focus(); + }); + + this.$menu.on('mouseenter', 'a', function(e) { + that.$menu.find('.active').removeClass('active'); + $(e.currentTarget).parent().not('.disabled').addClass('active'); + }); + + this.$menu.on('mouseleave', 'a', function() { + that.$menu.find('.active').removeClass('active'); + }); + }, + + val: function(value) { + + if (value != undefined) { + this.$element.val( value ); + + this.$element.change(); + return this.$element; + } else { + return this.$element.val(); + } + }, + + selectAll: function() { + this.$element.find('option').prop('selected', true).attr('selected', 'selected'); + this.render(); + }, + + deselectAll: function() { + this.$element.find('option').prop('selected', false).removeAttr('selected'); + this.render(); + }, + + keydown: function(e) { + var $this, + $items, + $parent, + index, + next, + first, + last, + prev, + nextPrev, + that, + prevIndex, + isActive, + keyCodeMap = { + 32:" ", 48:"0", 49:"1", 50:"2", 51:"3", 52:"4", 53:"5", 54:"6", 55:"7", 56:"8", 57:"9", 59:";", + 65:"a", 66:"b", 67:"c", 68:"d", 69:"e", 70:"f", 71:"g", 72:"h", 73:"i", 74:"j", 75:"k", 76:"l", + 77:"m", 78:"n", 79:"o", 80:"p", 81:"q", 82:"r", 83:"s", 84:"t", 85:"u", 86:"v", 87:"w", 88:"x", + 89:"y", 90:"z", 96:"0", 97:"1", 98:"2", 99:"3", 100:"4", 101:"5", 102:"6", 103:"7", 104:"8", 105:"9" + }; + + $this = $(this); + + $parent = $this.parent(); + + if ($this.is('input')) $parent = $this.parent().parent(); + + that = $parent.data('this'); + + if (that.options.liveSearch) $parent = $this.parent().parent(); + + if (that.options.container) $parent = that.$menu; + + $items = $('[role=menu] li:not(.divider) a', $parent); + + isActive = that.$menu.parent().hasClass('open'); + + if (that.options.liveSearch) { + if (/(^9$|27)/.test(e.keyCode) && isActive && that.$menu.find('.active').length == 0) { + e.preventDefault(); + that.$menu.parent().removeClass('open'); + that.$button.focus(); + } + $items = $('[role=menu] li:not(.divider):visible', $parent); + if (!$this.val() && !/(38|40)/.test(e.keyCode)) { + if ($items.filter('.active').length == 0) { + $items = that.$newElement.find('li').filter(':icontains(' + keyCodeMap[e.keyCode] + ')'); + } + } + } + + if (!$items.length) return; + + if (/(38|40)/.test(e.keyCode)) { + + if (!isActive) { + that.$menu.parent().addClass('open'); + } + + index = $items.index($items.filter(':focus')); + first = $items.parent(':not(.disabled):visible').first().index(); + last = $items.parent(':not(.disabled):visible').last().index(); + next = $items.eq(index).parent().nextAll(':not(.disabled):visible').eq(0).index(); + prev = $items.eq(index).parent().prevAll(':not(.disabled):visible').eq(0).index(); + nextPrev = $items.eq(next).parent().prevAll(':not(.disabled):visible').eq(0).index(); + + if (that.options.liveSearch) { + $items.each(function(i) { + if ($(this).is(':not(.disabled)')) { + $(this).data('index', i); + } + }); + index = $items.index($items.filter('.active')); + first = $items.filter(':not(.disabled):visible').first().data('index'); + last = $items.filter(':not(.disabled):visible').last().data('index'); + next = $items.eq(index).nextAll(':not(.disabled):visible').eq(0).data('index'); + prev = $items.eq(index).prevAll(':not(.disabled):visible').eq(0).data('index'); + nextPrev = $items.eq(next).prevAll(':not(.disabled):visible').eq(0).data('index'); + } + + prevIndex = $this.data('prevIndex'); + + if (e.keyCode == 38) { + if (that.options.liveSearch) index -= 1; + if (index != nextPrev && index > prev) index = prev; + if (index < first) index = first; + if (index == prevIndex) index = last; + } + + if (e.keyCode == 40) { + if (that.options.liveSearch) index += 1; + if (index == -1) index = 0; + if (index != nextPrev && index < next) index = next; + if (index > last) index = last; + if (index == prevIndex) index = first; + } + + $this.data('prevIndex', index); + + if (!that.options.liveSearch) { + $items.eq(index).focus(); + } else { + e.preventDefault(); + if (!$this.is('.dropdown-toggle')) { + $items.removeClass('active'); + $items.eq(index).addClass('active').find('a').focus(); + $this.focus(); + } + } + + } else if (!$this.is('input')) { + + var keyIndex = []; + + $items.each(function() { + if ($(this).parent().is(':not(.disabled)')) { + if ($.trim($(this).text().toLowerCase()).substring(0,1) == keyCodeMap[e.keyCode]) { + keyIndex.push($(this).parent().index()); + } + } + }); + + var count = $(document).data('keycount'); + count++; + $(document).data('keycount',count); + + var prevKey = $.trim($(':focus').text().toLowerCase()).substring(0,1); + + if (prevKey != keyCodeMap[e.keyCode]) { + count = 1; + $(document).data('keycount',count); + } else if (count >= keyIndex.length) { + $(document).data('keycount',0); + } + + $items.eq(keyIndex[count - 1]).focus(); + } + + // Select focused option if "Enter", "Spacebar", "Tab" are pressed inside the menu. + if (/(13|32|^9$)/.test(e.keyCode) && isActive) { + if (!/(32)/.test(e.keyCode)) e.preventDefault(); + if (!that.options.liveSearch) { + $(':focus').click(); + } else if (!/(32)/.test(e.keyCode)) { + that.$menu.find('.active a').click(); + $this.focus(); + } + $(document).data('keycount',0); + } + + if ((/(^9$|27)/.test(e.keyCode) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode) && !isActive)) { + that.$menu.parent().removeClass('open'); + that.$button.focus(); + } + + }, + + hide: function() { + this.$newElement.hide(); + }, + + show: function() { + this.$newElement.show(); + }, + + destroy: function() { + this.$newElement.remove(); + this.$element.remove(); + } + }; + + $.fn.selectpicker = function(option, event) { + //get the args of the outer function.. + var args = arguments; + var value; + var chain = this.each(function() { + if ($(this).is('select')) { + var $this = $(this), + data = $this.data('selectpicker'), + options = typeof option == 'object' && option; + + if (!data) { + $this.data('selectpicker', (data = new Selectpicker(this, options, event))); + } else if (options) { + for(var i in options) { + data.options[i] = options[i]; + } + } + + if (typeof option == 'string') { + //Copy the value of option, as once we shift the arguments + //it also shifts the value of option. + var property = option; + if (data[property] instanceof Function) { + [].shift.apply(args); + value = data[property].apply(data, args); + } else { + value = data.options[property]; + } + } + } + }); + + if (value != undefined) { + return value; + } else { + return chain; + } + }; + + $.fn.selectpicker.defaults = { + style: 'btn-default', + size: 'auto', + title: null, + selectedTextFormat : 'values', + noneSelectedText : 'Nothing selected', + countSelectedText: '{0} of {1} selected', + width: false, + container: false, + hideDisabled: false, + showSubtext: false, + showIcon: true, + showContent: true, + dropupAuto: true, + header: false, + liveSearch: false + }; + + $(document) + .data('keycount', 0) + .on('keydown', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bootstrap-select-searchbox input', Selectpicker.prototype.keydown); + +}(window.jQuery); diff --git a/js/data_migrate.js b/js/data_migrate.js index 820d111..9bf620a 100644 --- a/js/data_migrate.js +++ b/js/data_migrate.js @@ -23,13 +23,16 @@ function migrateArchiveData (user) { console.log("MIGRATING DATA"); - convertDataToDict(data); + if(typeof(data) == 'string') { + convertDataToDict(data); + } + else { + convertDataToV2_2(data); + } }) } - - // converts csv data to dictionary function convertDataToDict(data) { @@ -80,8 +83,9 @@ function convertDataToDict(data) { // set the system setting parameter to storage.set(system_setting, function() { - alert('Data migration successful'); - location.reload(); + //alert('Data migration successful'); + //location.reload(); + convertBucketToDict(data); }) }) @@ -93,4 +97,73 @@ function convertDataToDict(data) { console.log('Error while converting data to new format.'); console.log("Error message: "+err.message) } +} + +// Converts data to v2.2 +function convertDataToV2_2(data) { + var userSetting_label = user + ":Setting"; + + storage.get(userSetting_label, function(items) { + if (items[userSetting_label]['data_version'] == 'v2') { + convertBucketsToV2_2(function() { + convertLinksToV2_2(data); + }); + } + }); +} + +function convertBucketsToV2_2(callback) { + var bucketContainer = user + ':Buckets'; + + storage.get(bucketContainer, function(items) { + var buckets = items[bucketContainer].split(';'); + + for (var b in buckets) { + if(buckets[b] == '') { + buckets.splice(b, 1); + } + } + + var bucketDict = {}; + bucketDict[bucketContainer] = buckets; + + storage.set(bucketDict, callback); + }); +} + +// Converts Bucket (which was stored previously as csv) to array of strings. +function convertLinksToV2_2(data) { + for (var link in data) { + var buckets = data[link]["bucket"]; + buckets = buckets.split(';'); + + data[link]['bucket'] = []; + + for (var b in buckets) { + if(buckets[b] != '') { + data[link]['bucket'].push(buckets[b]); + } + } + } + + // set the userSetting field to data_version: v2.2 This indicates that the data has already been migrated and no need to call the migrateData routine. + var userSetting_label = user + ":Setting"; + + storage.get(userSetting_label, function(system_settings) { + system_settings[userSetting_label]['data_version'] = 'v2.2'; + + // temperory object to be able to store content in chrome storage + var toStore_data = {}; + toStore_data[user] = data; + + // set the new dictionary data + storage.set(toStore_data, function() { + // set the system setting parameter to + storage.set(system_settings, function() { + alert('Data migration successful'); + location.reload(); + }) + + }) + }); } \ No newline at end of file diff --git a/js/manageBuckets.js b/js/manageBuckets.js index 2fcd400..f3f5f88 100644 --- a/js/manageBuckets.js +++ b/js/manageBuckets.js @@ -23,8 +23,8 @@ function displayExistingBuckets() { if (typeof buckets == 'undefined' || buckets == '') return ; - //buckets are stored in csv format - buckets = buckets.split(";"); + //buckets are stored in csv format [Old Version] + //buckets = buckets.split(";"); for (var i=0;i -1) { + buckets.splice(index, 1); + } // tagging answers tagged to old bucket to new bucket for (var i in userLinks) { var temp_answer_bucket = userLinks[i]["bucket"]; - if(temp_answer_bucket == bucket) - userLinks[i]["bucket"] = newBucket; + for (var b in temp_answer_bucket) { + if(temp_answer_bucket[b] == bucket) { + var ansbuckets = userLinks[i]["bucket"]; + var i = ansbuckets.indexOf(bucket); + + if (i > -1) { + if(newBucket == '') { + ansbuckets.splice(i, 1); + } + else { + ansbuckets[b] = newBucket; + } + } + } + } } diff --git a/js/menuAction.js b/js/menuAction.js index a7ca839..8944713 100644 --- a/js/menuAction.js +++ b/js/menuAction.js @@ -507,7 +507,7 @@ $('#classifyAnswers').bind('click', function() { // bucket selected in the dropdown var bucket = $('#answerBucketDD').val(); - + storage.get(user, function(items) { var userLinks = items[user];