// V.2.0. (function() { var slimMarkdown = true; var storage = { set: function( name, object) { localStorage.setItem( name, JSON.stringify( object ) ); }, get: function( name ) { return JSON.parse( localStorage.getItem( name ) ); }, remove: function( name ) { localStorage.removeItem( name ); } }; storage.name = '2for1-sale'; // storage.remove( storage.name ); storage.data = storage.get( storage.name ); String.prototype.trimAll = function(){ return this.trim().replace(/\s+/g,' '); } // https://github.com/Mikhus/domurl !function(t){"use strict";var y=/^[a-z]+:/,d=/[-a-z0-9]+(\.[-a-z0-9])*:\d+/i,v=/\/\/(.*?)(?::(.*?))?@/,r=/^win/i,g=/:$/,m=/^\?/,q=/^#/,w=/(.*\/)/,A=/^\/{2,}/,I=/(^\/?)/,e=/'/g,o=/%([ef][0-9a-f])%([89ab][0-9a-f])%([89ab][0-9a-f])/gi,n=/%([cd][0-9a-f])%([89ab][0-9a-f])/gi,i=/%([0-7][0-9a-f])/gi,s=/\+/g,a=/^\w:$/,C=/[^/#?]/;var p,S="undefined"==typeof window&&"undefined"!=typeof global&&"function"==typeof require,b=!S&&t.navigator&&t.navigator.userAgent&&~t.navigator.userAgent.indexOf("MSIE"),x=S?t.require:null,j={protocol:"protocol",host:"hostname",port:"port",path:"pathname",query:"search",hash:"hash"},z={ftp:21,gopher:70,http:80,https:443,ws:80,wss:443};function E(){return S?p=p||"file://"+(process.platform.match(r)?"/":"")+x("fs").realpathSync("."):"about:srcdoc"===document.location.href?self.parent.document.location.href:document.location.href}function h(t,r,e){var o,n,i;r=r||E(),S?o=x("url").parse(r):(o=document.createElement("a")).href=r;var a,s,p=(s={path:!0,query:!0,hash:!0},(a=r)&&y.test(a)&&(s.protocol=!0,s.host=!0,d.test(a)&&(s.port=!0),v.test(a)&&(s.user=!0,s.pass=!0)),s);for(n in i=r.match(v)||[],j)p[n]?t[n]=o[j[n]]||"":t[n]="";if(t.protocol=t.protocol.replace(g,""),t.query=t.query.replace(m,""),t.hash=F(t.hash.replace(q,"")),t.user=F(i[1]||""),t.pass=F(i[2]||""),t.port=z[t.protocol]==t.port||0==t.port?"":t.port,!p.protocol&&C.test(r.charAt(0))&&(t.path=r.split("?")[0].split("#")[0]),!p.protocol&&e){var h=new L(E().match(w)[0]),u=h.path.split("/"),c=t.path.split("/"),f=["protocol","user","pass","host","port"],l=f.length;for(u.pop(),n=0;n', { css: { position: 'fixed', top: 0, right: 0, bottom: 0, left: 0, zIndex: 999998, display: 'block', width: '100%', height: '100%', background: '#fff', opacity: .95 } }).prependTo('body'); storage.data = { category: [], books: {}, }; var saleSubmenuExists = $('div.bc-color-background-active.in-page-nav-selected-tab-highlight').length; var viewAllLinksExists = $('[id^="carousel-PRODUCT"] > div > div > div > div:nth-child(1) > div > a').length > 0; var selector = (saleSubmenuExists) ? $('.adbl-main div[role="tab"] > a') : '[id^="carousel-PRODUCT"]'; $(selector).each(function() { var categoryURL = ''; var categoryName = ''; // SALE FRONT PAGE STYLE: multiple carousels if ( viewAllLinksExists ) { // Differentiating the possible "wishlist" carousel row from all others by using the "View all" link that exists in all other rows. var viewAllLink = $(this).find('> div > div > div > div:nth-child(1) > div.bc-col.bc-spacing-top-micro.bc-text-right.bc-col-last.bc-col-3 > a'); if ( viewAllLink.length > 0 ) { categoryName = $(this).find('> div > div > div > div:nth-child(1) > div.bc-col > [id^="adbl-carousel-heading-"]').text().trimAll(); categoryURL = viewAllLink.attr('href'); } } // SALE FRONT PAGE STYLE: horizontal sub menu with all categories side by side else if ( saleSubmenuExists ) { categoryName = $(this).text().trimAll(); categoryURL = $(this).attr('href'); } if ( categoryURL && categoryName ) { var strURL = categoryURL.lastIndexOf( window.location.origin ) > -1 ? categoryURL : window.location.origin + categoryURL; var url = new Url( strURL ); var node = url.query.node; url.clearQuery(); url.query.node = node; url.query.pageSize = '50'; url.query.page = '1'; url.query.bp_ua = 'yes'; url = url.toString(); storage.data.category.push({ url: url, name: categoryName }); storage.data.books[categoryName] = []; } }); if ( storage.data.category.length > 0 ) { // A recursive function that gets called over and over again until every single required page has been processed loadPage(); } else { console.log("Error: could not find category urls. Make sure you are in the front page of the sale.") } } function loadPage( subPages ) { if ( storage.data.category.length > 0 ) { var url; if ( subPages ) { url = new Url( storage.data.category[0].url ); url.query.page = subPages[0]; url = url.toString(); } else { url = storage.data.category[0].url; } console.log( url ); var iframe = $(''); iframe.prependTo('body'); iframe.on("load", function() { var audible = iframe.contents().find('body'); iframe[0].contentDocument.defaultView.stop(); if ( !subPages ) { // var paginationExists = audible.find('[data-bc-a11y-dynamic-skiplink-display-value="Pagination"]').length; var lastPageNumberEl = audible.find('#pagination-a11y-skiplink-target .pageNumberElement[data-value]:last'); subPages = []; if ( lastPageNumberEl.length > 0 ) { var lastPageNumber = parseFloat( lastPageNumberEl.data('value') ); subPages = _.range(1, lastPageNumber+1); subPages.shift(); } } else { subPages.shift(); } console.log( '\n\nCATEGORY: ' + storage.data.category[0].name + '\n\n' ); // Get data var contentWrapper = audible.find('.adbl-impression-container[data-widget="productList"]'); var titles = contentWrapper.find('.productListItem'); titles.each(fetchBookDetails); // Move to next page if ( subPages.length > 0 ) { loadPage( subPages.length > 0 ? subPages : null ); } // Move to next category else if ( storage.data.category.length > 0 ) { storage.data.category.shift(); loadPage(); } iframe.remove(); }); } // End of line else { delete storage.data.category; storage.set( storage.name, storage.data ); processOutput( storage.data.books ); } } // Goes through ever row of titles in the current page and fetches relevant data function fetchBookDetails() { var row = $(this); // Cover and sample var leftColumn = row.find('> div > div.bc-col-responsive.bc-spacing-top-none.bc-col-8 > div > div.bc-col-responsive.bc-col-5 > div > div > div.bc-col-responsive.bc-spacing-top-none.bc-col-9 > div > div.bc-col-responsive.bc-col-4 > div'); if ( leftColumn.length < 1 ) leftColumn = row.find('> div > div.bc-col-responsive.bc-spacing-top-none.bc-col-9 > div > div.bc-col-responsive.bc-col-4 > div'); if ( leftColumn.length < 1 ) leftColumn = row.find('> div > div.bc-col-responsive.bc-spacing-top-none.bc-col-8 > div > div.bc-col-responsive.bc-col-5 > div'); // Title, authors, narrators, series, rating var middleColumn = row.find('> div > div.bc-col-responsive.bc-spacing-top-none.bc-col-8 > div > div.bc-col-responsive.bc-col-6 > div'); if (middleColumn.length < 1) middleColumn = row.find('> div > div.bc-col-responsive.bc-spacing-top-none.bc-col-9 > div > div.bc-col-responsive.bc-col-7 > div'); // Sale counter, add to sale selection, more options var rightColumn = row.find('#adbl-buy-box-area'); var book = {}; var cover = leftColumn.find('[data-bc-hires]'); if ( cover.length > 0 ) book.cover = cover.attr('src'); else if ( cover.length < 1 ) { cover = row.find('img[data-lazy]'); if ( cover.length > 0 ) book.cover = cover.attr('data-lazy'); } middleColumn.find('> div > span > ul > div').remove(); var title = middleColumn.find('> div > span > ul > li:nth-child(1) > h3 > a'); book.title = title.length > 0 ? title.text().trimAll() : null; var authors = middleColumn.find('li.bc-list-item.authorLabel a'); book.authors = authors.length > 0 ? makeLinkArray( authors ) : null; var narrators = middleColumn.find('li.bc-list-item.narratorLabel a'); book.narrators = narrators.length > 0 ? makeLinkArray( narrators ) : null; var series = middleColumn.find('li.bc-list-item.seriesLabel a'); if ( series.length > 0 ) { var seriesString = middleColumn.find('li.bc-list-item.seriesLabel').html().trimAll(); seriesString = seriesString.substring(seriesString.indexOf(':')+1).trim(); // string = string.match(/,(*,)/g); seriesString = $.parseHTML(seriesString); var series = []; $.each( seriesString, function( index, object ) { var string = object.textContent.trim().replace(/^\,/,'').trim().replace(/\,$/, ""); var titleRow = (index+1) % 2; var numberRow = !titleRow; if ( titleRow ) { series.push({ name: string, page: object.href }); } else if ( numberRow ) { if ( string.match(/\d/) ) { // Trims text from the front ("Book ") and splits numbers separated by commas var numbers = string.replace(/^[^0-9]*/g, '').trim().split(','); // Numbers are added to the previous item var lastItem = series[ series.length-1 ]; lastItem.bookNumbers = jQuery.map( numbers, function( n, i ) { return parseFloat( n ); }); } } }); book.series = series.length > 0 ? series : null; } else { book.series = null; } var length = middleColumn.find('li.bc-list-item.runtimeLabel span'); book.length = length.length > 0 ? length.text().split(':')[1].trimAll() : null; var releaseDate = middleColumn.find('li.bc-list-item.releaseDateLabel span'); book.releaseDate = releaseDate.length > 0 ? releaseDate.text().split(':')[1].trimAll() : null; var language = middleColumn.find('li.bc-list-item.languageLabel span'); book.language = language.length > 0 ? language.text().split(':')[1].trimAll() : null; var rating = middleColumn.find('li.ratingsLabel > span:first'); book.rating = (function( rating ) { if ( rating.length > 0 ) { var regex = rating.text().trimAll().match(/([0-9]\.[0-9]|[0-9])+/); } return regex ? regex[0] : null; })( rating ); var ratings = middleColumn.find('li.ratingsLabel > span:last'); book.ratings = (function( ratings ) { if ( ratings.length > 0 ) { var regex = ratings.text().trimAll().match(/([0-9]|\,)+/g); } return regex ? regex[0] : null; })( ratings ); var sample = leftColumn.find('[data-mp3]'); book.sample = sample.length > 0 ? sample.data('mp3') : null; book.page = title.length > 0 ? window.location.origin + title.attr('href').split('?')[0] + '?ipRedirectOverride=true&overrideBaseCountry=true' : null; console.log( '['+ storage.data.books[ storage.data.category[0].name ].length +']: ' + book.title ); storage.data.books[ storage.data.category[0].name ].push( book ); book = null; } function makeLinkArray( links ) { var array = []; links.each(function() { var url = window.location.origin + $(this).attr('href'); url = new Url( url ); var searchNarrator; if ( url.query.searchNarrator ) searchNarrator = url.query.searchNarrator; url.clearQuery(); if ( searchNarrator ) url.query.searchNarrator = searchNarrator; url.query.ipRedirectOverride = true; url.query.overrideBaseCountry = true; url = url.toString(); array.push({ name: $(this).text().trimAll(), page: url }); }); return array; } function slugify(text) { const from = "ãàáäâẽèéëêìíïîõòóöôùúüûñç·/_,:;" const to = "aaaaaeeeeeiiiiooooouuuunc------" const newText = text.split('').map( (letter, i) => letter.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i))) return newText .toString() // Cast to string .toLowerCase() // Convert the string to lowercase letters .trim() // Remove whitespace from both sides of a string .replace(/\s+/g, '-') // Replace spaces with - .replace(/&/g, '-and-') // Replace & with 'and' .replace(/[^\w\-]+/g, '') // Remove all non-word chars .replace(/\-\-+/g, '-'); // Replace multiple - with single - } function linkArrayToMarkdown( array, series ) { var md = []; $.each( array, function( key, object ) { var bookNumbers = series && object.bookNumbers ? ' book ' + object.bookNumbers.join(',') : ''; md.push( '[' + object.name + ']('+ object.page +')' + bookNumbers ); }); return md.join(', '); } function linkArrayToHTML( array, series ) { var html = []; $.each( array, function( key, object ) { var bookNumbers = series && object.bookNumbers ? ' book ' + object.bookNumbers.join(',') : ''; html.push( ''+ object.name +'' + bookNumbers ); }); return html.join(', '); } function processOutput( uniqueBoys ) { var markdown = ''; var html = ''; var plaintext = ''; // Simple menu for html var navItems = (function() { var items = []; $.each( storage.data.books, function( categoryName ) { items.push( '' ); }); return items.join(''); }()); html += ''; $.each( storage.data.books, function( categoryName, category ) { output( categoryName, category ); }); function output( categoryName, category, unique ) { // Category heading var newAdditions = (unique ? ' (New additions)' : ''); markdown += '\n\n### ' + categoryName + newAdditions + '\n\n'; html += '\n\n

'+ categoryName + newAdditions + '

\n'; plaintext += '\n\n' + categoryName + newAdditions + '\n\n'; // Books $.each( category, function( index, book ) { // MARKDOWN /* title */ markdown += (index+1) + '. ['+ book.title +']('+ book.page +') \n' ; if ( !slimMarkdown ) { /* authors */ markdown += ' - **Authors:** ' + linkArrayToMarkdown( book.authors ) + '\n'; /* narrators */ markdown += ' - **Narrators:** ' + linkArrayToMarkdown( book.narrators ) + '\n'; /* series */ if (book.series) markdown += ' - **Series:** ' + linkArrayToMarkdown(book.series, true) + '\n'; /* sample */ if (book.sample) markdown += ' - **Sample:** [play sample](' + book.sample + ') \n'; /* length */ markdown += ' - **Length:** ' + book.length + '\n' ; /* released */ markdown += ' - **Released:** ' + book.releaseDate + '\n' ; /* language */ if ( book.language ) markdown += ' - **Language:** ' + book.language + '\n'; } /* rating */ if ( book.rating ) markdown += ' - **Rating:** ' + book.rating + ' ('+ book.ratings +') \n'; // HTML html += '\n\n
\n' + '
\n' + '
\n'+ ''+ book.title +' \n' + '
Authors: ' + linkArrayToHTML( book.authors ) + '
'+ '
Narrators: ' + linkArrayToHTML( book.narrators ) + '
'+ (book.series ? '
Series: ' + linkArrayToHTML( book.series, true ) + '
' : '') + (book.sample ? '
Sample: play sample
' : '') + '
Length: '+ book.length +'
\n' + '
Released: '+ book.releaseDate +'
\n' + (book.language ? '
Language: '+ book.language +'
\n' : '') + (book.rating ? '
Rating: '+ book.rating + ' ('+ book.ratings +')' +'
\n' : '') + '
\n' + '
\n'; // PLAINTEXT plaintext += book.title + ' → '+ book.page +' \n\n'; }); } // HTML styling html = ' \n\n' + html; $('body').html(''); var textareaCSS = { width: '100%', height: 200, marginBottom: 30 }; $('').appendTo('body'); var row = $('
').appendTo('body'); var markdownWrapper = $('
').appendTo( row ); $('Markdown:').appendTo( markdownWrapper ); $('