<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel rdf:about="https://let.hatelabo.jp/toyoshi/rss">
    <link>https://let.hatelabo.jp/toyoshi/rss</link>
    <description></description>
    <title>Bookmarklets from toyoshi</title>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="https://let.hatelabo.jp/toyoshi/let/kpmFyNTKgoAA"/>
        <rdf:li rdf:resource="https://let.hatelabo.jp/toyoshi/let/hJmc5bbModRV"/>
        <rdf:li rdf:resource="https://let.hatelabo.jp/toyoshi/let/hLHUp8KY8Y11"/>
      </rdf:Seq>
    </items>
  </channel>
  <item rdf:about="https://let.hatelabo.jp/toyoshi/let/kpmFyNTKgoAA">
    <link>https://let.hatelabo.jp/toyoshi/let/kpmFyNTKgoAA</link>
    <dc:date>2024-11-27T01:02:06Z</dc:date>
    <description>my bookmarklet</description>
    <dc:creator>toyoshi</dc:creator>
    <title>[Let] bookmarklet</title>
    <content:encoded>&lt;a href="javascript:%22https%3A%2F%2Flet.st-hatelabo.com%2Ftoyoshi%2Flet%2FkpmFyNTKgoAA.bookmarklet.js%20%28arg%29%22.replace%28%2F%28%5CS%2B%29%5Cs%2B%28%5CS%2A%29%2F%2Cfunction%28s%2Curl%2Carg%29%7Bs%3Ddocument.createElement%28%22script%22%29%3Bs.charset%3D%22utf-8%22%3Bs.src%3Durl%2B%22%3Fs%3D%22%2BencodeURIComponent%28arg%29%3Bdocument.body.appendChild%28s%29%7D%29%3Bvoid%280%29%3B"&gt;bookmarklet&lt;/a&gt;&lt;pre&gt;/*
 * @title bookmarklet
 * @description my bookmarklet
 * @include http://*
 * @license MIT License
 * @require 
 */


  // Create an audio context
  const audioContext = new (window.AudioContext || window.webkitAudioContext)();

  // Function to play a tone of 852Hz
  function play852HzTone(durationInSeconds = 2) {
    // Create an oscillator node
    const oscillator = audioContext.createOscillator();
    
    // Set the frequency to 852Hz
    oscillator.frequency.setValueAtTime(852, audioContext.currentTime);

    // Set the waveform type (sine wave is default)
    oscillator.type = 'sine';

    // Connect the oscillator to the audio context's destination (speakers)
    oscillator.connect(audioContext.destination);

    // Start the oscillator
    oscillator.start();

    // Stop the oscillator after the specified duration
    oscillator.stop(audioContext.currentTime + durationInSeconds);
  }

  // Play the 852Hz tone for 2 seconds
  play852HzTone();&lt;/pre&gt;</content:encoded>
  </item>
  <item rdf:about="https://let.hatelabo.jp/toyoshi/let/hJmc5bbModRV">
    <link>https://let.hatelabo.jp/toyoshi/let/hJmc5bbModRV</link>
    <dc:date>2016-02-29T05:04:09Z</dc:date>
    <description>my bookmarklet</description>
    <dc:creator>toyoshi</dc:creator>
    <title>[Let] bookmarklet</title>
    <content:encoded>&lt;a href="javascript:%22https%3A%2F%2Flet.st-hatelabo.com%2Ftoyoshi%2Flet%2FhJmc5bbModRV.bookmarklet.js%20%28arg%29%22.replace%28%2F%28%5CS%2B%29%5Cs%2B%28%5CS%2A%29%2F%2Cfunction%28s%2Curl%2Carg%29%7Bs%3Ddocument.createElement%28%22script%22%29%3Bs.charset%3D%22utf-8%22%3Bs.src%3Durl%2B%22%3Fs%3D%22%2BencodeURIComponent%28arg%29%3Bdocument.body.appendChild%28s%29%7D%29%3Bvoid%280%29%3B"&gt;bookmarklet&lt;/a&gt;&lt;pre&gt;/*
 * @title bookmarklet
 * @description my bookmarklet
 * @include http://*
 * @license MIT License
 * @require 
 */

//Amazonの注文履歴をCSV形式にして出力するスクリプト
//
//以下のスクリプトを参考に作成されました。
//http://moroya.hatenablog.jp/entry/2013/06/03/225935
//
//CSVに成型しているのは14行目から定義されているformatEntryという関数なので、これを書き換えれば自由な書式で出力できます。
(function(){

	// 各注文履歴をCSVフォーマットにして返す
	var datePattern = new RegExp(&amp;quot;(\\d{4})年(\\d{1,2})月(\\d{1,2})日&amp;quot;);
	function formatEntry(entry) {
		entry.date.match(datePattern);
		var year = RegExp.$1;
		var month = RegExp.$2; if (month.length &amp;lt;= 1) month = &amp;quot;0&amp;quot; + month;
		var day = RegExp.$3; if (day.length &amp;lt;= 1) day = &amp;quot;0&amp;quot; + day;
		var item = entry.item.split(&amp;quot;,&amp;quot;).join(&amp;quot;\\,&amp;quot;);
		return year + &amp;quot;/&amp;quot; + month + &amp;quot;/&amp;quot; + day + &amp;quot;,&amp;quot; + entry.price + &amp;quot;,&amp;quot; + item + &amp;quot;\n&amp;quot;;
	}

	// 一つの注文に含まれる複数の物品名をつなぐ文字列
	var itemDelimiter = &amp;quot; / &amp;quot;;

	var total = {};
	var year = '2014';
	var all = false;
	function init(num) {
		if(typeof num !== 'number') {
			num = 0;
			$('&amp;lt;div/&amp;gt;').css({
				position: 'fixed',
				left: 0,
				top: 0,
				width: '100%',
				height: '100%',
				zIndex: 1000,
				backgroundColor: 'rgba(0,0,0,.7)',
				color: '#fff',
				fontSize: 30,
				textAlign: 'center',
				paddingTop: '15em'
			}).attr('id', '___overlay').text('Amazonいくら使った？').appendTo('body');
			year = window.prompt('何年分の注文を集計しますか？\n半角数字4桁で入力してください\n（全期間を集計する場合は「all」と入力）', year);
			if(year === 'all') {
				all = true;
				year = $('#orderFilter option:last').val().match(/[0-9]/g).join('');
			} else if(!/^[0-9]{4}$/.test(year)) {
				alert('正しい数値を入力してください');
				$('#___overlay').remove();
				return false;
			}
			year = Number(year);
		}
		var progress = load(num);
		$('#___overlay').text(year+'年の集計中…  / '+(num+1)+'ページ目');
		progress.done(function(results){
			if (typeof total[year] ===  'undefined') {
				total[year] = results;
			} else {
				total[year] = total[year].concat(results);
			}
			init(num+1);
		}).fail(function(){
			if(all &amp;amp;&amp;amp; new Date().getFullYear() &amp;gt; year) {
				year++;
				init(0);
			} else {
				var txt = 'あなたは\n';
				var _contents = &amp;quot;&amp;quot;;
				var _total = 0;
				$.each(total, function(year, results){
					var yen = 0;
					$.each(results, function(){
						yen += this.price;
						_contents += formatEntry(this);
					});
					txt += year + '年 合計' + addFigure(yen) + '円分\n';
					_total += yen;
				});
				if(all) txt += '総計' + addFigure(_total) + '円分\n';
				popup(_contents).alert(txt + 'の買い物をAmazonでしました！');
				$('#___overlay').remove();
			}
		});
	}
 
	function load(num) {
		var df = $.Deferred();
		var page = get(num);
		page.done(function(data){
			var dom = $.parseHTML(data);
			var results = [];

			$(dom).find('.action-box').each(function(){
				var box = $(this);

				var dateText = $(box.find('h2')[0]).text();

				var items = [];
				box.find('.item-title').each(function(){ items.push($(this).text().trim()); });
				var item = items.join(itemDelimiter);

				var priceText = $(box.find('.price')[0]).text();
				var price = Number(priceText.match(/[0-9]/g).join(''));

				console.log(item, price);
				results.push({'date':dateText,'item':item,'price':price});
			});

			if(results.length &amp;lt;= 0) df.reject();
			else df.resolve(results);
		});
		return df.promise();
	}
 
	function get(num) {
		var df = $.Deferred();
		$.ajax({
			url: 'https://www.amazon.co.jp/gp/css/order-history/?orderFilter=year-'+year+'&amp;amp;startIndex='+num*10,
			success: function(data){
				df.resolve(data);
			}
		});
		return df.promise();
	}
 
	function addFigure(str) {
		var num = new String(str).replace(/,/g, &amp;quot;&amp;quot;);
		while(num != (num = num.replace(/^(-?\d+)(\d{3})/, &amp;quot;$1,$2&amp;quot;)));
		return num;
	}

	function popup(content) {
		var generator=window.open('','name','height=250,width=700');
		generator.document.write('&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Amazon to CSV&amp;lt;/title&amp;gt;');
		generator.document.write('&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;');
		generator.document.write('&amp;lt;pre&amp;gt;');
		generator.document.write(content);
		generator.document.write('&amp;lt;/pre&amp;gt;');
		generator.document.write('&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;');
		generator.document.close();
		return generator;
	}

	var entityMap = {
		&amp;quot;&amp;amp;&amp;quot;: &amp;quot;&amp;amp;amp;&amp;quot;,
		&amp;quot;&amp;lt;&amp;quot;: &amp;quot;&amp;amp;lt;&amp;quot;,
		&amp;quot;&amp;gt;&amp;quot;: &amp;quot;&amp;amp;gt;&amp;quot;,
		'&amp;quot;': '&amp;amp;quot;',
		&amp;quot;'&amp;quot;: '&amp;amp;#39;',
		&amp;quot;/&amp;quot;: '&amp;amp;#47;'
	};
	var entityPatern = new RegExp(&amp;quot;[&amp;amp;&amp;lt;&amp;gt;\&amp;quot;'\/]&amp;quot;, &amp;quot;g&amp;quot;);
	function escapeHtml(string) {
		return String(string).replace(entityPattern, function (s) {
			return entityMap[s];
		});
	}

	if(typeof $ !== 'function') {
		var d=document;
		var s=d.createElement('script');
		s.src='//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js';
		s.onload=init;
		d.body.appendChild(s);
	} else {
		init();
	}
})();
&lt;/pre&gt;</content:encoded>
  </item>
  <item rdf:about="https://let.hatelabo.jp/toyoshi/let/hLHUp8KY8Y11">
    <link>https://let.hatelabo.jp/toyoshi/let/hLHUp8KY8Y11</link>
    <dc:date>2015-11-25T02:55:19Z</dc:date>
    <description>各カードのタイトルに（xx分）と書いておくと、その分数を合計してリストのタイトル横に終了予定時間を表示します。</description>
    <dc:creator>toyoshi</dc:creator>
    <title>[Let] Trelloのタスクの終了時間を計算するブックマークレット</title>
    <content:encoded>&lt;a href="javascript:var%20get_minute%3Dfunction%28title%29%7Bvar%20match_result%3Bmatch_result%3Dtitle.match%28%2F%28%5Cd%2B%29%E5%88%86%2F%29%3Breturn%20%24.isArray%28match_result%29%3FNumber%28match_result.pop%28%29%29%3A0%7D%3Bvar%20sum%3Dfunction%28a%29%7Bvar%20amount%3D0%3Ba.forEach%28%28function%28elm%29%7Bamount%2B%3Delm%7D%29%29%3Breturn%20amount%7D%3B%24%28%27.end_time%27%29.remove%28%29%3B%24%28%27.js-list%27%29.each%28%28function%28%29%7Bresult%3D%24%28%27.list-card.js-member-droppable%27%2C%24%28this%29%29.map%28%28function%28%29%7Breturn%20get_minute%28%24%28%27a.js-card-name%27%2C%24%28this%29%29.text%28%29%29%7D%29%29.toArray%28%29%3Bvar%20date%3Dnew%20Date%3Bdate.setMinutes%28date.getMinutes%28%29%2Bsum%28result%29%29%3B%24%28%27.js-list-name%27%2Cthis%29.append%28%27%3Cspan%20class%3D%22end_time%22%3E%28%27%2B%28%220%22%2Bdate.getHours%28%29%29.slice%28-2%29%2B%27%3A%27%2B%28%220%22%2Bdate.getMinutes%28%29%29.slice%28-2%29%2B%27%29%3C%2Fspan%3E%27%29%7D%29%29%3B"&gt;Trelloのタスクの終了時間を計算するブックマークレット&lt;/a&gt;&lt;pre&gt;/*
 * @title Trelloのタスクの終了時間を計算するブックマークレット
 * @description 各カードのタイトルに（xx分）と書いておくと、その分数を合計してリストのタイトル横に終了予定時間を表示します。
 * @include https://*
 * @license MIT License
 * @javascript_url 
 */

var get_minute = function(title){
	var match_result;
	match_result = title.match(/(\d+)分/);
	return $.isArray(match_result) ? Number(match_result.pop()) : 0;
};

var sum = function(a){    
	var amount = 0;
    a.forEach(function(elm) {
        amount += elm;
    });
    return amount;
};

$('.end_time').remove();
$('.js-list').each(
	function(){
		result = $('.list-card.js-member-droppable',$(this)).map(
			function(){
				return get_minute($('a.js-card-name', $(this)).text());
			}
		).toArray(); 
		var date = new Date();
		date.setMinutes(date.getMinutes() + sum(result));
		$('.js-list-name', this).append('&amp;lt;span class=&amp;quot;end_time&amp;quot;&amp;gt;('+(&amp;quot;0&amp;quot;+date.getHours()).slice(-2)+':'+(&amp;quot;0&amp;quot; + date.getMinutes()).slice(-2)+')&amp;lt;/span&amp;gt;');
	}
);&lt;/pre&gt;</content:encoded>
  </item>
</rdf:RDF>
